Make it build

This commit is contained in:
Stefan Markovic 2021-11-06 00:27:30 +01:00
parent ea7341bd1b
commit 79bd4031be
107 changed files with 9848 additions and 25 deletions

View file

@ -2,14 +2,31 @@
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.App"
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.WinUI3">
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
<ResourceDictionary Source="/Controls/KeyVisual/KeyVisual.xaml" />
<ResourceDictionary Source="/Controls/IsEnabledTextBlock/IsEnabledTextBlock.xaml" />
<ResourceDictionary Source="/Styles/TextBlock.xaml" />
<ResourceDictionary Source="/Styles/Button.xaml"/>
<ResourceDictionary Source="/Themes/Colors.xaml"/>
<ResourceDictionary Source="/Themes/SettingsExpanderStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
<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" />
</Style>
<Style TargetType="controls:CheckBoxWithDescriptionControl" BasedOn="{StaticResource DefaultCheckBoxStyle}" />
</ResourceDictionary>
</Application.Resources>
</Application>

View file

@ -1,20 +1,9 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Microsoft.UI.Xaml.Shapes;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using System.Globalization;
using Microsoft.PowerToys.Settings.UI.Library;
// TODO(stefan)
using WindowsUI = Windows.UI;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
@ -46,6 +35,15 @@ namespace Microsoft.PowerToys.Settings.UI.WinUI3
m_window.Activate();
}
public static bool IsDarkTheme()
{
var selectedTheme = SettingsRepository<GeneralSettings>.GetInstance(settingsUtils).SettingsConfig.Theme.ToUpper(CultureInfo.InvariantCulture);
var defaultTheme = new WindowsUI.ViewManagement.UISettings();
var uiTheme = defaultTheme.GetColorValue(WindowsUI.ViewManagement.UIColorType.Background).ToString(System.Globalization.CultureInfo.InvariantCulture);
return selectedTheme == "DARK" || (selectedTheme == "SYSTEM" && uiTheme == "#FF000000");
}
private Window m_window;
private static ISettingsUtils settingsUtils = new SettingsUtils();
}
}

View file

@ -0,0 +1,138 @@
// 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.WinUI3.Services;
using Microsoft.Xaml.Interactivity;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
using WinUI = Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Behaviors
{
public class NavigationViewHeaderBehavior : Behavior<WinUI.NavigationView>
{
private static NavigationViewHeaderBehavior current;
private Page currentPage;
public DataTemplate DefaultHeaderTemplate { get; set; }
public object DefaultHeader
{
get { return GetValue(DefaultHeaderProperty); }
set { SetValue(DefaultHeaderProperty, value); }
}
public static readonly DependencyProperty DefaultHeaderProperty = DependencyProperty.Register("DefaultHeader", typeof(object), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => current.UpdateHeader()));
public static NavigationViewHeaderMode GetHeaderMode(Page item)
{
return (NavigationViewHeaderMode)item?.GetValue(HeaderModeProperty);
}
public static void SetHeaderMode(Page item, NavigationViewHeaderMode value)
{
item?.SetValue(HeaderModeProperty, value);
}
public static readonly DependencyProperty HeaderModeProperty =
DependencyProperty.RegisterAttached("HeaderMode", typeof(bool), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(NavigationViewHeaderMode.Always, (d, e) => current.UpdateHeader()));
public static object GetHeaderContext(Page item)
{
return item?.GetValue(HeaderContextProperty);
}
public static void SetHeaderContext(Page item, object value)
{
item?.SetValue(HeaderContextProperty, value);
}
public static readonly DependencyProperty HeaderContextProperty =
DependencyProperty.RegisterAttached("HeaderContext", typeof(object), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => current.UpdateHeader()));
public static DataTemplate GetHeaderTemplate(Page item)
{
return (DataTemplate)item?.GetValue(HeaderTemplateProperty);
}
public static void SetHeaderTemplate(Page item, DataTemplate value)
{
item?.SetValue(HeaderTemplateProperty, value);
}
public static readonly DependencyProperty HeaderTemplateProperty =
DependencyProperty.RegisterAttached("HeaderTemplate", typeof(DataTemplate), typeof(NavigationViewHeaderBehavior), new PropertyMetadata(null, (d, e) => current.UpdateHeaderTemplate()));
protected override void OnAttached()
{
base.OnAttached();
current = this;
NavigationService.Navigated += OnNavigated;
}
protected override void OnDetaching()
{
base.OnDetaching();
NavigationService.Navigated -= OnNavigated;
}
private void OnNavigated(object sender, NavigationEventArgs e)
{
var frame = sender as Frame;
if (frame.Content is Page page)
{
currentPage = page;
UpdateHeader();
UpdateHeaderTemplate();
}
}
private void UpdateHeader()
{
if (currentPage != null)
{
var headerMode = GetHeaderMode(currentPage);
if (headerMode == NavigationViewHeaderMode.Never)
{
AssociatedObject.Header = null;
AssociatedObject.AlwaysShowHeader = false;
}
else
{
var headerFromPage = GetHeaderContext(currentPage);
if (headerFromPage != null)
{
AssociatedObject.Header = headerFromPage;
}
else
{
AssociatedObject.Header = DefaultHeader;
}
if (headerMode == NavigationViewHeaderMode.Always)
{
AssociatedObject.AlwaysShowHeader = true;
}
else
{
AssociatedObject.AlwaysShowHeader = false;
}
}
}
}
private void UpdateHeaderTemplate()
{
if (currentPage != null)
{
var headerTemplate = GetHeaderTemplate(currentPage);
AssociatedObject.HeaderTemplate = headerTemplate ?? DefaultHeaderTemplate;
}
}
}
}

View file

@ -0,0 +1,13 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Behaviors
{
public enum NavigationViewHeaderMode
{
Always,
Never,
Minimal,
}
}

View file

@ -0,0 +1,71 @@
// 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;
using Microsoft.UI.Xaml.Media;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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() { Margin = new Thickness(0, 10, 0, 0), Text = Header });
panel.Children.Add(new IsEnabledTextBlock() { FontSize = (double)App.Current.Resources["SecondaryTextFontSize"], Foreground = (SolidColorBrush)App.Current.Resources["TextFillColorSecondaryBrush"], 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(object),
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,41 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Controls.ColorPickerButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:clr="using:Windows.UI"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<!--TODO(stefan)<muxc:DropDownButton Padding="4,4,8,4" AutomationProperties.FullDescription="{x:Bind clr:ColorHelper.ToDisplayName(SelectedColor), Mode=OneWay }">-->
<muxc:DropDownButton Padding="4,4,8,4">
<Border x:Name="ColorPreviewBorder"
Width="48"
CornerRadius="2"
Height="24"
BorderBrush="{ThemeResource CardBorderBrush}"
BorderThickness="{ThemeResource CardBorderThickness}">
<Border.Background>
<SolidColorBrush Color="{x:Bind SelectedColor, Mode=OneWay}"/>
</Border.Background>
</Border>
<muxc:DropDownButton.Flyout>
<Flyout>
<muxc:ColorPicker IsColorSliderVisible="True"
IsColorChannelTextInputVisible="True"
IsHexInputVisible="True"
IsAlphaEnabled="False"
IsAlphaSliderVisible="False"
IsAlphaTextInputVisible="False"
Color="{x:Bind SelectedColor, Mode=TwoWay}" />
</Flyout>
</muxc:DropDownButton.Flyout>
</muxc: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 Windows.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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,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.WinUI3.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,35 @@
<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.WinUI3.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>
<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>
<TextBlock x:Name="Label"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
FontFamily="{TemplateBinding FontFamily}"
Foreground="{TemplateBinding Foreground}"
TextWrapping="WrapWholeWords"
Text="{TemplateBinding Text}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</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 Windows.System;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Markup;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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,124 @@
<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.WinUI3.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>
<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>
<Rectangle x:Name="ContentHolder"
Fill="{TemplateBinding Background}"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BorderThickness}"
RadiusX="4"
RadiusY="4"
Height="{TemplateBinding Height}"
MinWidth="{TemplateBinding MinWidth}"/>
<ContentPresenter x:Name="KeyPresenter"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}"
Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"
FontSize="{TemplateBinding FontSize}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SmallTextKeyVisualStyle" TargetType="local:KeyVisual" BasedOn="{StaticResource DefaultTextKeyVisualStyle}">
<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" TargetType="local:KeyVisual" BasedOn="{StaticResource DefaultTextKeyVisualStyle}">
<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" TargetType="local:KeyVisual" BasedOn="{StaticResource DefaultTextKeyVisualStyle}">
<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" TargetType="local:KeyVisual" BasedOn="{StaticResource DefaultTextKeyVisualStyle}">
<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" TargetType="local:KeyVisual" BasedOn="{StaticResource DefaultTextKeyVisualStyle}">
<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,47 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.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"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="280" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image x:Name="HeaderImage"
Source="{x:Bind ModuleImageSource}"
Stretch="UniformToFill" />
<ScrollViewer Grid.Row="1"
VerticalScrollBarVisibility="Auto"
Padding="32,24,32,24">
<StackPanel Orientation="Vertical"
VerticalAlignment="Top">
<TextBlock x:Name="TitleTxt"
Text="{x:Bind ModuleTitle}"
AutomationProperties.HeadingLevel="Level1"
Style="{StaticResource TitleTextBlockStyle}" />
<TextBlock x:Name="DescriptionTxt"
Margin="0,8,0,0"
Text="{x:Bind ModuleDescription}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap" />
<ContentPresenter x:Name="ModuleContentPresenter"
Content="{x:Bind ModuleContent}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Margin="0,12,0,0"/>
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>

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.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Controls
{
public sealed partial class OOBEPageControl : UserControl
{
public OOBEPageControl()
{
this.InitializeComponent();
}
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 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 ModuleContentProperty = DependencyProperty.Register("ModuleContent", typeof(object), typeof(SettingsPageControl), new PropertyMetadata(new Grid()));
}
}

View file

@ -0,0 +1,157 @@
// 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.WinUI3.Controls
{
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
[TemplatePart(Name = PartIconPresenter, Type = typeof(ContentPresenter))]
[TemplatePart(Name = PartDescriptionPresenter, Type = typeof(ContentPresenter))]
public class Setting : ContentControl
{
private const string PartIconPresenter = "IconPresenter";
private const string PartDescriptionPresenter = "DescriptionPresenter";
private ContentPresenter _iconPresenter;
private ContentPresenter _descriptionPresenter;
private Setting _setting;
public Setting()
{
this.DefaultStyleKey = typeof(Setting);
}
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
"Header",
typeof(string),
typeof(Setting),
new PropertyMetadata(default(string), OnHeaderChanged));
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
"Description",
typeof(object),
typeof(Setting),
new PropertyMetadata(null, OnDescriptionChanged));
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
"Icon",
typeof(object),
typeof(Setting),
new PropertyMetadata(default(string), OnIconChanged));
public static readonly DependencyProperty ActionContentProperty = DependencyProperty.Register(
"ActionContent",
typeof(object),
typeof(Setting),
null);
[Localizable(true)]
public string Header
{
get => (string)GetValue(HeaderProperty);
set => SetValue(HeaderProperty, value);
}
[Localizable(true)]
public object Description
{
get => (object)GetValue(DescriptionProperty);
set => SetValue(DescriptionProperty, value);
}
public object Icon
{
get => (object)GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
public object ActionContent
{
get => (object)GetValue(ActionContentProperty);
set => SetValue(ActionContentProperty, value);
}
protected override void OnApplyTemplate()
{
IsEnabledChanged -= Setting_IsEnabledChanged;
_setting = (Setting)this;
_iconPresenter = (ContentPresenter)_setting.GetTemplateChild(PartIconPresenter);
_descriptionPresenter = (ContentPresenter)_setting.GetTemplateChild(PartDescriptionPresenter);
Update();
SetEnabledState();
IsEnabledChanged += Setting_IsEnabledChanged;
base.OnApplyTemplate();
}
private static void OnHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Setting)d).Update();
}
private static void OnIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Setting)d).Update();
}
private static void OnDescriptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Setting)d).Update();
}
private void Setting_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetEnabledState();
}
private void SetEnabledState()
{
VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true);
}
private void Update()
{
if (_setting == null)
{
return;
}
if (_setting.ActionContent != null)
{
if (_setting.ActionContent.GetType() != typeof(Button))
{
// We do not want to override the default AutomationProperties.Name of a button. Its Content property already describes what it does.
if (!string.IsNullOrEmpty(_setting.Header))
{
AutomationProperties.SetName((UIElement)_setting.ActionContent, _setting.Header);
}
}
}
if (_setting._iconPresenter != null)
{
if (_setting.Icon == null)
{
_setting._iconPresenter.Visibility = Visibility.Collapsed;
}
else
{
_setting._iconPresenter.Visibility = Visibility.Visible;
}
}
if (_setting.Description == null)
{
_setting._descriptionPresenter.Visibility = Visibility.Collapsed;
}
else
{
_setting._descriptionPresenter.Visibility = Visibility.Visible;
}
}
}
}

View file

@ -0,0 +1,106 @@
<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.WinUI3.Controls">
<Style TargetType="controls:Setting">
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
<Setter Property="Background" Value="{ThemeResource CardBackgroundBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource CardBorderThickness}" />
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="16" />
<Setter Property="Margin" Value="0,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:Setting">
<Grid x:Name="RootGrid"
CornerRadius="{TemplateBinding CornerRadius}"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
MinHeight="48">
<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}" />
<Setter Target="IconPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<!-- Icon -->
<ColumnDefinition Width="*"/>
<!-- Header and subtitle -->
<ColumnDefinition Width="Auto"/>
<!-- Action control -->
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="IconPresenter"
Content="{TemplateBinding Icon}"
HorizontalAlignment="Center"
FontSize="20"
Margin="2,0,18,0"
MaxWidth="26"
AutomationProperties.AccessibilityView="Raw"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Foreground="{ThemeResource CardPrimaryForegroundBrush}"
VerticalAlignment="Center"/>
<StackPanel
VerticalAlignment="Center"
Grid.Column="1"
HorizontalAlignment="Stretch"
Margin="0,0,16,0">
<TextBlock
x:Name="HeaderPresenter"
Text="{TemplateBinding Header}"
VerticalAlignment="Center"
Foreground="{ThemeResource CardPrimaryForegroundBrush}" />
<ContentPresenter
x:Name="DescriptionPresenter"
Content="{TemplateBinding Description}"
FontSize="{StaticResource SecondaryTextFontSize}"
TextWrapping="WrapWholeWords"
Foreground="{ThemeResource TextFillColorSecondaryBrush}">
<ContentPresenter.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource CaptionTextBlockStyle}">
<Style.Setters>
<Setter Property="TextWrapping" Value="WrapWholeWords"/>
</Style.Setters>
</Style>
<Style TargetType="HyperlinkButton" BasedOn="{StaticResource TextButtonStyle}">
<Style.Setters>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Padding" Value="0,0,0,0"/>
</Style.Setters>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</StackPanel>
<ContentPresenter
x:Name="ContentPresenter"
Content="{TemplateBinding ActionContent}"
Grid.Column="2"
VerticalAlignment="Center"
HorizontalAlignment="Right" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View file

@ -0,0 +1,38 @@
// 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.Automation;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Controls
{
public partial class SettingExpander : Expander
{
public SettingExpander()
{
DefaultStyleKey = typeof(Expander);
this.Style = (Style)App.Current.Resources["SettingExpanderStyle"];
this.RegisterPropertyChangedCallback(Expander.HeaderProperty, OnHeaderChanged);
}
private static void OnHeaderChanged(DependencyObject d, DependencyProperty dp)
{
SettingExpander self = (SettingExpander)d;
if (self.Header != null)
{
if (self.Header.GetType() == typeof(Setting))
{
Setting selfSetting = (Setting)self.Header;
selfSetting.Style = (Style)App.Current.Resources["ExpanderHeaderSettingStyle"];
if (!string.IsNullOrEmpty(selfSetting.Header))
{
AutomationProperties.SetName(self, selfSetting.Header);
}
}
}
}
}
}

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.ComponentModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Controls
{
/// <summary>
/// Represents a control that can contain multiple settings (or other) controls
/// </summary>
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
public partial class SettingsGroup : ItemsControl
{
public SettingsGroup()
{
DefaultStyleKey = typeof(SettingsGroup);
}
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
"Header",
typeof(string),
typeof(SettingsGroup),
new PropertyMetadata(default(string)));
[Localizable(true)]
public string Header
{
get => (string)GetValue(HeaderProperty);
set => SetValue(HeaderProperty, value);
}
protected override void OnApplyTemplate()
{
IsEnabledChanged -= SettingsGroup_IsEnabledChanged;
SetEnabledState();
IsEnabledChanged += SettingsGroup_IsEnabledChanged;
base.OnApplyTemplate();
}
private void SettingsGroup_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetEnabledState();
}
private void SetEnabledState()
{
VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true);
}
protected override AutomationPeer OnCreateAutomationPeer()
{
return new SettingsGroupAutomationPeer(this);
}
}
}

View file

@ -0,0 +1,48 @@
<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.WinUI3.Controls">
<Style TargetType="controls:SettingsGroup">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel 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">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="HeaderPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="HeaderPresenter"
Text="{TemplateBinding Header}"
Grid.Row="0"
Style="{ThemeResource BodyStrongTextBlockStyle}"
Margin="1,32,0,8"
AutomationProperties.HeadingLevel="Level2"/>
<ItemsPresenter Grid.Row="1"/>
</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.WinUI3.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.WinUI3.Controls
{
public class PageLink
{
public string Text { get; set; }
public Uri Link { get; set; }
}
}

View file

@ -0,0 +1,117 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Controls.SettingsPageControl"
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.WinUI3.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<UserControl.Resources>
<converters:DoubleToVisibilityConverter x:Name="doubleToVisibilityConverter" GreaterThan="0" TrueValue="Visible" FalseValue="Collapsed" />
</UserControl.Resources>
<Grid RowSpacing="24" Padding="20,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock x:Name="Header"
Text="{x:Bind ModuleTitle}"
AutomationProperties.HeadingLevel="1"
Style="{StaticResource TitleTextBlockStyle}"
Margin="0,44,0,0"
VerticalAlignment="Stretch"/>
<ScrollViewer Grid.Row="1">
<Grid RowSpacing="24"
Padding="0,0,20,48" >
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="1048" Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Top panel -->
<Grid ColumnSpacing="16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border CornerRadius="4" VerticalAlignment="Top">
<Image AutomationProperties.AccessibilityView="Raw">
<Image.Source>
<BitmapImage UriSource="{x:Bind ModuleImageSource}" />
</Image.Source>
</Image>
</Border>
<StackPanel Grid.Column="1">
<TextBlock x:Name="AboutDescription"
Text="{x:Bind ModuleDescription}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap"/>
<ItemsControl ItemsSource="{x:Bind PrimaryLinks}" IsTabStop="False" Margin="0,8,0,0">
<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 Orientation="Horizontal" HorizontalSpacing="24"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</Grid>
<!-- Content panel -->
<ContentPresenter x:Name="ModuleContentPresenter"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Content="{x:Bind ModuleContent}"
MaxWidth="1048"
Margin="0,12,0,0" Grid.Row="1"/>
<!-- Bottom panel -->
<StackPanel x:Name="SecondaryLinksPanel"
Grid.Row="2"
Visibility="{x:Bind SecondaryLinks.Count, Converter={StaticResource doubleToVisibilityConverter}}"
Orientation="Vertical">
<TextBlock Text="{x:Bind SecondaryLinksHeader}"
Style="{ThemeResource BodyStrongTextBlockStyle}"
Margin="2,8,0,0"
AutomationProperties.HeadingLevel="Level2"/>
<ItemsControl x:Name="SecondaryLinksItemControl" IsTabStop="False" Margin="2,0,0,0" 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 Orientation="Horizontal" HorizontalSpacing="24"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</Grid>
</ScrollViewer>
</Grid>
</UserControl>

View file

@ -0,0 +1,74 @@
// 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.WinUI3.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);
}
#pragma warning disable CA2227 // Collection properties should be read only
public ObservableCollection<PageLink> PrimaryLinks
#pragma warning restore CA2227 // Collection properties should be read only
{
get => (ObservableCollection<PageLink>)GetValue(PrimaryLinksProperty);
set => SetValue(PrimaryLinksProperty, value);
}
public string SecondaryLinksHeader
{
get { return (string)GetValue(SecondaryLinksHeaderProperty); }
set { SetValue(SecondaryLinksHeaderProperty, value); }
}
#pragma warning disable CA2227 // Collection properties should be read only
public ObservableCollection<PageLink> SecondaryLinks
#pragma warning restore CA2227 // Collection properties should be read only
{
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()));
}
}

View file

@ -0,0 +1,48 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Controls.ShortcutControl"
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.WinUI3.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="LayoutRoot"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid HorizontalAlignment="Right">
<StackPanel Orientation="Horizontal">
<Button x:Name="EditButton"
Background="Transparent"
BorderBrush="Transparent"
Click="OpenDialogButton_Click" >
<StackPanel Orientation="Horizontal"
Spacing="16">
<ItemsControl x:Name="PreviewKeysControl"
IsEnabled="{Binding ElementName=EditButton, Path=IsEnabled}"
VerticalAlignment="Center"
IsTabStop="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:KeyVisual IsTabStop="False"
AutomationProperties.AccessibilityView="Raw"
VisualType="Small"
VerticalAlignment="Center"
Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<FontIcon Glyph="&#xE104;"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="14"
Margin="0,0,4,0" />
</StackPanel>
</Button>
</StackPanel>
</Grid>
</UserControl>

View file

@ -0,0 +1,408 @@
// 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.WinUI3.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Windows.ApplicationModel.Resources;
using Windows.UI.Core;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
// TODO(stefan) Microsoft namespace is added to the front for some reason :S
using WindowsSystem = Windows.System;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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);
ResourceLoader resourceLoader = ResourceLoader.GetForCurrentView();
// 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"),
CloseButtonText = resourceLoader.GetString("Activation_Shortcut_Cancel"),
DefaultButton = ContentDialogButton.Primary,
};
shortcutDialog.PrimaryButtonClick += ShortcutDialog_PrimaryButtonClick;
shortcutDialog.Opened += ShortcutDialog_Opened;
shortcutDialog.Closing += ShortcutDialog_Closing;
}
private void ShortcutControl_Unloaded(object sender, RoutedEventArgs e)
{
shortcutDialog.PrimaryButtonClick -= ShortcutDialog_PrimaryButtonClick;
shortcutDialog.Opened -= ShortcutDialog_Opened;
shortcutDialog.Closing -= ShortcutDialog_Closing;
// Dispose the HotkeySettingsControlHook object to terminate the hook threads when the textbox is unloaded
hook.Dispose();
}
private void KeyEventHandler(int key, bool matchValue, int matchValueCode)
{
switch ((WindowsSystem.VirtualKey)key)
{
case WindowsSystem.VirtualKey.LeftWindows:
case WindowsSystem.VirtualKey.RightWindows:
internalSettings.Win = matchValue;
break;
case WindowsSystem.VirtualKey.Control:
case WindowsSystem.VirtualKey.LeftControl:
case WindowsSystem.VirtualKey.RightControl:
internalSettings.Ctrl = matchValue;
break;
case WindowsSystem.VirtualKey.Menu:
case WindowsSystem.VirtualKey.LeftMenu:
case WindowsSystem.VirtualKey.RightMenu:
internalSettings.Alt = matchValue;
break;
case WindowsSystem.VirtualKey.Shift:
case WindowsSystem.VirtualKey.LeftShift:
case WindowsSystem.VirtualKey.RightShift:
_shiftToggled = true;
internalSettings.Shift = matchValue;
break;
case WindowsSystem.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 ((WindowsSystem.VirtualKey)key == WindowsSystem.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)WindowsSystem.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)WindowsSystem.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 async void Hotkey_KeyDown(int key)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
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 async void Hotkey_KeyUp(int key)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
KeyEventHandler(key, false, 0);
});
}
private bool Hotkey_IsActive()
{
return _isActive;
}
#pragma warning disable CA1801 // Review unused parameters
private void ShortcutDialog_Opened(ContentDialog sender, ContentDialogOpenedEventArgs args)
#pragma warning restore CA1801 // Review unused parameters
{
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)WindowsSystem.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;
await shortcutDialog.ShowAsync();
}
#pragma warning disable CA1801 // Review unused parameters
private void ShortcutDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
#pragma warning restore CA1801 // Review unused parameters
{
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;
}
}
#pragma warning disable CA1801 // Review unused parameters
private void ShortcutDialog_Closing(ContentDialog sender, ContentDialogClosingEventArgs args)
#pragma warning restore CA1801 // Review unused parameters
{
_isActive = false;
}
private void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects)
hook.Dispose();
}
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
// TODO: set large fields to 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,94 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Controls.ShortcutDialogContentControl"
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.WinUI3.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"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
mc:Ignorable="d"
x:Name="ShortcutContentControl">
<UserControl.Resources>
<converters:BoolToVisibilityConverter x:Key="boolToVisibilityConverter" FalseValue="Collapsed" TrueValue="Visible" />
</UserControl.Resources>
<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"
Height="56"
Grid.Row="1"
Margin="0,64,0,0"
HorizontalContentAlignment="Center"
ItemsSource="{x:Bind Keys, Mode=OneWay}"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="8"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:KeyVisual AutomationProperties.AccessibilityView="Raw"
Height="56"
VisualType="Large"
IsError="{Binding ElementName=ShortcutContentControl, Path=IsError, Mode=OneWay}"
IsTabStop="False"
Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Orientation="Vertical"
Grid.Row="2"
Spacing="8"
Margin="0,24,0,0"
VerticalAlignment="Top">
<Grid Height="36">
<Border x:Name="WarningBanner"
Background="{ThemeResource InfoBarErrorSeverityBackgroundBrush}"
CornerRadius="{ThemeResource ControlCornerRadius}"
BorderBrush="{ThemeResource InfoBarBorderBrush}"
BorderThickness="{ThemeResource InfoBarBorderThickness}"
Padding="8"
Margin="-2,0,0,0"
Visibility="{Binding ElementName=ShortcutContentControl, Path=IsError, Mode=OneWay, Converter={StaticResource boolToVisibilityConverter}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!--TODO(stefan)<muxc:InfoBadge AutomationProperties.AccessibilityView="Raw"
Margin="2,0,12,0"
Style="{StaticResource CriticalIconInfoBadgeStyle}" />-->
<TextBlock x:Name="InvalidShortcutWarningLabel"
x:Uid="InvalidShortcut"
VerticalAlignment="Center"
Margin="0,-1,0,0"
Foreground="{ThemeResource InfoBarTitleForeground}"
FontWeight="{ThemeResource InfoBarTitleFontWeight}"
Grid.Column="1" />
</Grid>
</Border>
</Grid>
<toolkitcontrols:MarkdownTextBlock x:Uid="InvalidShortcutWarningLabel"
FontSize="12"
Background="Transparent"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"/>
</StackPanel>
</Grid>
</UserControl>

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.Collections.Generic;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Controls
{
public sealed partial class ShortcutDialogContentControl : UserControl
{
public ShortcutDialogContentControl()
{
this.InitializeComponent();
}
#pragma warning disable CA2227 // Collection properties should be read only
public List<object> Keys
#pragma warning restore CA2227 // Collection properties should be read only
{
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,43 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Controls.ShortcutWithTextLabelControl"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ItemsControl AutomationProperties.AccessibilityView="Raw"
ItemsSource="{x:Bind Keys}"
VerticalAlignment="Center"
IsTabStop="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:KeyVisual IsTabStop="False"
AutomationProperties.AccessibilityView="Raw"
VisualType="SmallOutline"
VerticalAlignment="Center"
Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<toolkitcontrols:MarkdownTextBlock Background="Transparent"
Text="{x:Bind Text}"
Margin="8,0,0,0"
Grid.Column="1"
VerticalAlignment="Center" />
</Grid>
</UserControl>

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.Collections.Generic;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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)));
#pragma warning disable CA2227 // Collection properties should be read only
public List<object> Keys
#pragma warning restore CA2227 // Collection properties should be read only
{
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,24 @@
// 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.Library;
using Microsoft.UI.Xaml.Data;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Converters
{
public sealed class AwakeModeToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var mode = (AwakeMode)value;
return (int)mode;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return (AwakeMode)Enum.ToObject(typeof(AwakeMode), (int)value);
}
}
}

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 System;
using System.Globalization;
using Windows.ApplicationModel.Resources;
using Microsoft.UI.Xaml.Data;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Converters
{
public sealed class ImageResizerFitToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var toLower = false;
if ((string)parameter == "ToLower")
{
toLower = true;
}
string targetValue = string.Empty;
switch (value)
{
case 0: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Fit_Fill_ThirdPersonSingular"); break;
case 1: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Fit_Fit_ThirdPersonSingular"); break;
case 2: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Fit_Stretch_ThirdPersonSingular"); break;
}
if (toLower)
{
targetValue = targetValue.ToLower(CultureInfo.CurrentCulture);
}
return targetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}
}

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 System;
using System.Globalization;
using Windows.ApplicationModel.Resources;
using Microsoft.UI.Xaml.Data;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Converters
{
public sealed class ImageResizerUnitToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var toLower = false;
if ((string)parameter == "ToLower")
{
toLower = true;
}
string targetValue = string.Empty;
switch (value)
{
case 0: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Unit_Centimeter"); break;
case 1: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Unit_Inch"); break;
case 2: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Unit_Percent"); break;
case 3: targetValue = ResourceLoader.GetForCurrentView().GetString("ImageResizer_Unit_Pixel"); break;
}
if (toLower)
{
targetValue = targetValue.ToLower(CultureInfo.CurrentCulture);
}
return targetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}
}

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 Microsoft.UI.Xaml.Data;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Converters
{
public sealed class UpdateStateToBoolConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null || parameter == null)
{
return false;
}
else
{
if (value.ToString() == (string)parameter)
{
return true;
}
else
{
return false;
}
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}
}

View file

@ -0,0 +1,86 @@
// 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.Runtime.InteropServices;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Helpers
{
internal static class NativeKeyboardHelper
{
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
internal struct INPUT
{
internal INPUTTYPE type;
internal InputUnion data;
internal static int Size
{
get { return Marshal.SizeOf(typeof(INPUT)); }
}
}
[StructLayout(LayoutKind.Explicit)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
internal struct InputUnion
{
[FieldOffset(0)]
internal MOUSEINPUT mi;
[FieldOffset(0)]
internal KEYBDINPUT ki;
[FieldOffset(0)]
internal HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
internal struct MOUSEINPUT
{
internal int dx;
internal int dy;
internal int mouseData;
internal uint dwFlags;
internal uint time;
internal UIntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
internal struct KEYBDINPUT
{
internal short wVk;
internal short wScan;
internal uint dwFlags;
internal int time;
internal UIntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:Accessible fields should begin with upper-case letter", Justification = "Matching Native Structure")]
internal struct HARDWAREINPUT
{
internal int uMsg;
internal short wParamL;
internal short wParamH;
}
internal enum INPUTTYPE : uint
{
INPUT_MOUSE = 0,
INPUT_KEYBOARD = 1,
INPUT_HARDWARE = 2,
}
[Flags]
internal enum KeyEventF
{
KeyDown = 0x0000,
ExtendedKey = 0x0001,
KeyUp = 0x0002,
Unicode = 0x0004,
Scancode = 0x0008,
}
}
}

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 System;
using System.Runtime.InteropServices;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Helpers
{
public static class NativeMethods
{
private const int GWL_STYLE = -16;
private const int WS_POPUP = 1 << 31; // 0x80000000
[DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs, NativeKeyboardHelper.INPUT[] pInputs, int cbSize);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern short GetAsyncKeyState(int vKey);
[DllImport("user32.dll", SetLastError = true)]
internal static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
internal static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
#pragma warning disable CA1401 // P/Invokes should not be visible
[DllImport("user32.dll")]
public static extern bool ShowWindow(System.IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern bool AllowSetForegroundWindow(int dwProcessId);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern bool FreeLibrary(IntPtr hModule);
#pragma warning restore CA1401 // P/Invokes should not be visible
public static void SetPopupStyle(IntPtr hwnd)
{
_ = SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_POPUP);
}
}
}

View file

@ -0,0 +1,33 @@
// 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.UI.Xaml.Controls;
using Microsoft.UI.Xaml;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Helpers
{
public static class NavHelper
{
// This helper class allows to specify the page that will be shown when you click on a NavigationViewItem
//
// Usage in xaml:
// <winui:NavigationViewItem x:Uid="Shell_Main" Icon="Document" helpers:NavHelper.NavigateTo="views:MainPage" />
//
// Usage in code:
// NavHelper.SetNavigateTo(navigationViewItem, typeof(MainPage));
public static Type GetNavigateTo(NavigationViewItem item)
{
return (Type)item?.GetValue(NavigateToProperty);
}
public static void SetNavigateTo(NavigationViewItem item, Type value)
{
item?.SetValue(NavigateToProperty, value);
}
public static readonly DependencyProperty NavigateToProperty =
DependencyProperty.RegisterAttached("NavigateTo", typeof(Type), typeof(NavHelper), new PropertyMetadata(null));
}
}

View file

@ -0,0 +1,27 @@
// 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.Runtime.CompilerServices;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Helpers
{
public class Observable : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
{
return;
}
storage = value;
OnPropertyChanged(propertyName);
}
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

View file

@ -0,0 +1,61 @@
// 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.Windows.Input;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Helpers
{
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action execute)
: this(execute, null)
{
}
public RelayCommand(Action execute, Func<bool> canExecute)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute();
public void Execute(object parameter) => _execute();
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "abstract T and abstract")]
public class RelayCommand<T> : ICommand
{
private readonly Action<T> execute;
private readonly Func<T, bool> canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
public RelayCommand(Action<T> execute, Func<T, bool> canExecute)
{
this.execute = execute ?? throw new ArgumentNullException(nameof(execute));
this.canExecute = canExecute;
}
public bool CanExecute(object parameter) => canExecute == null || canExecute((T)parameter);
public void Execute(object parameter) => execute((T)parameter);
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}

View file

@ -0,0 +1,18 @@
// 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 Windows.ApplicationModel.Resources;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Helpers
{
internal static class ResourceExtensions
{
private static readonly ResourceLoader ResLoader = new ResourceLoader();
public static string GetLocalized(this string resourceKey)
{
return ResLoader.GetString(resourceKey);
}
}
}

View file

@ -0,0 +1,18 @@
// 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.Diagnostics;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Helpers
{
public static class StartProcessHelper
{
public const string ColorsSettings = "ms-settings:colors";
public static void Start(string process)
{
Process.Start(new ProcessStartInfo(process) { UseShellExecute = true });
}
}
}

View file

@ -0,0 +1,14 @@
{
"Projects": [
{
"LanguageSet": "Azure_Languages",
"LocItems": [
{
"SourceFile": "src\\settings-ui\\Microsoft.PowerToys.Settings.UI.WinUI3\\Strings\\en-us\\Resources.resw",
"CopyOption": "LangIDOnName",
"OutputPath": "src\\settings-ui\\Microsoft.PowerToys.Settings.UI.WinUI3\\Strings"
}
]
}
]
}

View file

@ -2,12 +2,12 @@
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.MainWindow"
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.WinUI3"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.WinUI3.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button x:Name="myButton" Click="myButton_Click">Click Me</Button>
</StackPanel>
<Grid>
<local:ShellPage/>
</Grid>
</Window>

View file

@ -30,7 +30,7 @@ namespace Microsoft.PowerToys.Settings.UI.WinUI3
private void myButton_Click(object sender, RoutedEventArgs e)
{
myButton.Content = "Clicked";
// myButton.Content = "Clicked";
}
}
}

View file

@ -32,12 +32,16 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.WinUI.UI" Version="7.1.1-preview3" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls" Version="7.1.1-preview3" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.0.0-preview3" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.20348.19" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.7" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
<ProjectReference Include="..\Microsoft.PowerToys.Settings.UI.Library\Microsoft.PowerToys.Settings.UI.Library.csproj" />
</ItemGroup>
</Project>

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.
namespace Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Enums
{
public enum PowerToysModulesEnum
{
Overview = 0,
Awake,
ColorPicker,
FancyZones,
FileExplorer,
ImageResizer,
KBM,
MouseUtils,
PowerRename,
Run,
ShortcutGuide,
VideoConference,
}
}

View file

@ -0,0 +1,79 @@
// 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.Telemetry.Events;
using Microsoft.PowerToys.Telemetry;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel
{
public class OobePowerToysModule
{
private System.Diagnostics.Stopwatch timeOpened = new System.Diagnostics.Stopwatch();
public string ModuleName { get; set; }
public string Tag { get; set; }
public bool IsNew { get; set; }
public string Image { get; set; }
public string Icon { get; set; }
public string FluentIcon { get; set; }
public string PreviewImageSource { get; set; }
public string Description { get; set; }
public string Link { get; set; }
public string DescriptionLink { get; set; }
public OobePowerToysModule()
{
}
public OobePowerToysModule(OobePowerToysModule other)
{
if (other == null)
{
return;
}
ModuleName = other.ModuleName;
Tag = other.Tag;
IsNew = other.IsNew;
Image = other.Image;
Icon = other.Icon;
FluentIcon = other.FluentIcon;
PreviewImageSource = other.PreviewImageSource;
Description = other.Description;
Link = other.Link;
DescriptionLink = other.DescriptionLink;
timeOpened = other.timeOpened;
}
public void LogOpeningSettingsEvent()
{
PowerToysTelemetry.Log.WriteEvent(new OobeSettingsEvent() { ModuleName = this.ModuleName });
}
public void LogRunningModuleEvent()
{
PowerToysTelemetry.Log.WriteEvent(new OobeModuleRunEvent() { ModuleName = this.ModuleName });
}
public void LogOpeningModuleEvent()
{
timeOpened.Start();
}
public void LogClosingModuleEvent()
{
timeOpened.Stop();
PowerToysTelemetry.Log.WriteEvent(new OobeSectionEvent() { Section = this.ModuleName, TimeOpenedMs = timeOpened.ElapsedMilliseconds });
}
}
}

View file

@ -0,0 +1,13 @@
// 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.
namespace Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel
{
public class OobeShellViewModel
{
public OobeShellViewModel()
{
}
}
}

View file

@ -0,0 +1,38 @@
<Page x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeAwake"
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"
mc:Ignorable="d"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_Awake_HowToUse" />
<TextBlock x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}"/>
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_Awake_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}"
Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_Awake"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</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.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views
{
public sealed partial class OobeAwake : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeAwake()
{
InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.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,40 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeColorPicker"
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"
mc:Ignorable="d"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<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 Background="Transparent" x:Uid="Oobe_ColorPicker_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="Launch_ColorPicker" Style="{StaticResource AccentButtonStyle}" Click="Start_ColorPicker_Click"/>
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_ColorPicker"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</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 Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views
{
public sealed partial class OobeColorPicker : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeColorPicker()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.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();
HotkeyControl.Keys = SettingsRepository<ColorPickerSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View file

@ -0,0 +1,40 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeFancyZones"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_FancyZones_HowToUse" />
<controls:ShortcutWithTextLabelControl x:Name="HotkeyControl" x:Uid="Oobe_FancyZones_HowToUse_Shortcut" />
<TextBlock x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}"/>
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_FancyZones_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_FancyZones"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</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.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views
{
public sealed partial class OobeFancyZones : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeFancyZones()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.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,33 @@
<Page x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeFileExplorer"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="Oobe_HowToEnable"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_FileExplorer_HowToEnable" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_PowerPreview"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</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.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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)PowerToysModulesEnum.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,38 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeImageResizer"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="Oobe_HowToLaunch"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_ImageResizer_HowToLaunch" />
<TextBlock x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}"/>
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_ImageResizer_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_ImageResizer"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</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.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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)PowerToysModulesEnum.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,37 @@
<Page x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeKBM"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="Oobe_HowToCreateMappings"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_KBM_HowToCreateMappings" />
<TextBlock x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}"/>
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_KBM_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_KBM"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</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.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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)PowerToysModulesEnum.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,33 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeMouseUtils"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="Oobe_MouseUtils_FindMyMouse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_MouseUtils_FindMyMouse_Description" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_MouseUtils"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</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.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views
{
public sealed partial class OobeMouseUtils : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeMouseUtils()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.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,34 @@
<Page x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeOverview"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}">
<controls:OOBEPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<TextBlock Margin="0,4,0,8"
x:Uid="Oobe_Overview_Description"
TextWrapping="Wrap"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.DescriptionLink}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="Oobe_Overview_DescriptionLinkText"
TextWrapping="Wrap" />
</HyperlinkButton>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="Oobe_Overview_LatestVersionLink"
TextWrapping="Wrap" />
</HyperlinkButton>
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</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.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views
{
public sealed partial class OobeOverview : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeOverview()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModulesEnum.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,37 @@
<Page x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobePowerRename"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_PowerRename_HowToUse" />
<TextBlock x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}"/>
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_PowerRename_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_PowerRename"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</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.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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)PowerToysModulesEnum.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,39 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeRun"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<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 Background="Transparent" x:Uid="Oobe_Run_TipsAndTricks" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="Launch_Run" Style="{StaticResource AccentButtonStyle}" Click="Start_Run_Click"/>
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_Run"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</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.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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)PowerToysModulesEnum.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,60 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeShellPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:winui="using:Microsoft.UI.Xaml.Controls"
xmlns:localModels="using:Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Loaded="UserControl_Loaded">
<!--TODO(stefan)winui:BackdropMaterial.ApplyToRootOrPageBackground="True"-->
<UserControl.Resources>
<DataTemplate x:Key="NavigationViewMenuItem" x:DataType="localModels:OobePowerToysModule">
<winui:NavigationViewItem Content="{x:Bind ModuleName}" Tag="{x:Bind Tag}">
<winui:NavigationViewItem.Icon>
<BitmapIcon UriSource="{x:Bind FluentIcon}" ShowAsMonochrome="False"/>
</winui:NavigationViewItem.Icon>
</winui:NavigationViewItem>
</DataTemplate>
</UserControl.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<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" />
<Setter Target="NavigationView.IsPaneToggleButtonVisible"
Value="True" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<winui:NavigationView IsSettingsVisible="False"
IsPaneToggleButtonVisible="False"
IsPaneOpen="True"
x:Name="NavigationView"
OpenPaneLength="296"
PaneDisplayMode="Left"
SelectionChanged="NavigationView_SelectionChanged"
IsBackButtonVisible="Collapsed"
MenuItemsSource="{x:Bind Modules, Mode=OneTime}"
MenuItemTemplate="{StaticResource NavigationViewMenuItem}">
<winui:NavigationView.Content>
<Frame x:Name="NavigationFrame" />
</winui:NavigationView.Content>
</winui:NavigationView>
</Grid>
</UserControl>

View file

@ -0,0 +1,263 @@
// 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.Diagnostics.CodeAnalysis;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Windows.ApplicationModel.Resources;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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; }
public OobeShellPage()
{
InitializeComponent();
DataContext = ViewModel;
OobeShellHandler = this;
UpdateUITheme();
Modules = new ObservableCollection<OobePowerToysModule>();
ResourceLoader loader = ResourceLoader.GetForViewIndependentUse();
Modules.Insert((int)PowerToysModulesEnum.Overview, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_Welcome"),
Tag = "Overview",
IsNew = false,
Icon = "\uEF3C",
Image = "ms-appx:///Assets/Modules/ColorPicker.png",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerToys.png",
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/OOBEPTHero.png",
DescriptionLink = "https://aka.ms/PowerToysOverview",
Link = "https://github.com/microsoft/PowerToys/releases/",
});
Modules.Insert((int)PowerToysModulesEnum.Awake, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_Awake"),
Tag = "Awake",
IsNew = false,
Icon = "\uEC32",
Image = "ms-appx:///Assets/Modules/Awake.png",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsAwake.png",
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/Awake.png",
Description = loader.GetString("Oobe_Awake_Description"),
Link = "https://aka.ms/PowerToysOverview_Awake",
});
Modules.Insert((int)PowerToysModulesEnum.ColorPicker, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_ColorPicker"),
Tag = "ColorPicker",
IsNew = false,
Icon = "\uEF3C",
Image = "ms-appx:///Assets/Modules/ColorPicker.png",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsColorPicker.png",
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/ColorPicker.gif",
Description = loader.GetString("Oobe_ColorPicker_Description"),
Link = "https://aka.ms/PowerToysOverview_ColorPicker",
});
Modules.Insert((int)PowerToysModulesEnum.FancyZones, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_FancyZones"),
Tag = "FancyZones",
IsNew = false,
Icon = "\uE737",
Image = "ms-appx:///Assets/Modules/FancyZones.png",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsFancyZones.png",
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/FancyZones.gif",
Description = loader.GetString("Oobe_FancyZones_Description"),
Link = "https://aka.ms/PowerToysOverview_FancyZones",
});
Modules.Insert((int)PowerToysModulesEnum.FileExplorer, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_FileExplorer"),
Tag = "FileExplorer",
IsNew = false,
Icon = "\uEC50",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsFileExplorerPreview.png",
Image = "ms-appx:///Assets/Modules/PowerPreview.png",
Description = loader.GetString("Oobe_FileExplorer_Description"),
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/FileExplorer.png",
Link = "https://aka.ms/PowerToysOverview_FileExplorerAddOns",
});
Modules.Insert((int)PowerToysModulesEnum.ImageResizer, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_ImageResizer"),
Tag = "ImageResizer",
IsNew = false,
Icon = "\uEB9F",
Image = "ms-appx:///Assets/Modules/ImageResizer.png",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsImageResizer.png",
Description = loader.GetString("Oobe_ImageResizer_Description"),
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/ImageResizer.gif",
Link = "https://aka.ms/PowerToysOverview_ImageResizer",
});
Modules.Insert((int)PowerToysModulesEnum.KBM, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_KBM"),
Tag = "KBM",
IsNew = false,
Icon = "\uE765",
Image = "ms-appx:///Assets/Modules/KeyboardManager.png",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsKeyboardManager.png",
Description = loader.GetString("Oobe_KBM_Description"),
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/KBM.gif",
Link = "https://aka.ms/PowerToysOverview_KeyboardManager",
});
Modules.Insert((int)PowerToysModulesEnum.MouseUtils, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_MouseUtils"),
Tag = "MouseUtils",
IsNew = true,
Icon = "\uE962",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsMouseUtils.png",
Image = "ms-appx:///Assets/Modules/MouseUtils.png",
Description = loader.GetString("Oobe_MouseUtils_Description"),
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/MouseUtils.gif",
Link = "https://aka.ms/PowerToysOverview_MouseUtilities", // TODO: Add correct link after it's been created.
});
Modules.Insert((int)PowerToysModulesEnum.PowerRename, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_PowerRename"),
Tag = "PowerRename",
IsNew = false,
Icon = "\uE8AC",
Image = "ms-appx:///Assets/Modules/PowerRename.png",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerRename.png",
Description = loader.GetString("Oobe_PowerRename_Description"),
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/PowerRename.gif",
Link = "https://aka.ms/PowerToysOverview_PowerRename",
});
Modules.Insert((int)PowerToysModulesEnum.Run, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_Run"),
Tag = "Run",
IsNew = false,
Icon = "\uE773",
Image = "ms-appx:///Assets/Modules/PowerLauncher.png",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerToysRun.png",
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/Run.gif",
Description = loader.GetString("Oobe_PowerRun_Description"),
Link = "https://aka.ms/PowerToysOverview_PowerToysRun",
});
Modules.Insert((int)PowerToysModulesEnum.ShortcutGuide, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_ShortcutGuide"),
Tag = "ShortcutGuide",
IsNew = false,
Icon = "\uEDA7",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsShortcutGuide.png",
Image = "ms-appx:///Assets/Modules/ShortcutGuide.png",
Description = loader.GetString("Oobe_ShortcutGuide_Description"),
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/OOBEShortcutGuide.png",
Link = "https://aka.ms/PowerToysOverview_ShortcutGuide",
});
Modules.Insert((int)PowerToysModulesEnum.VideoConference, new OobePowerToysModule()
{
ModuleName = loader.GetString("Oobe_VideoConference"),
Tag = "VideoConference",
IsNew = true,
Icon = "\uEC50",
FluentIcon = "ms-appx:///Assets/FluentIcons/FluentIconsVideoConferenceMute.png",
Image = "ms-appx:///Assets/Modules/VideoConference.png",
Description = loader.GetString("Oobe_VideoConference_Description"),
PreviewImageSource = "ms-appx:///Assets/Modules/OOBE/VideoConferenceMute.png",
Link = "https://aka.ms/PowerToysOverview_VideoConference",
});
}
public void OnClosing()
{
if (NavigationView.SelectedItem != null)
{
((OobePowerToysModule)NavigationView.SelectedItem).LogClosingModuleEvent();
}
}
private void UserControl_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (Modules.Count > 0)
{
NavigationView.SelectedItem = Modules[(int)PowerToysModulesEnum.Overview];
}
}
[SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "Params are required for event handler signature requirements.")]
private void NavigationView_SelectionChanged(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewSelectionChangedEventArgs args)
{
OobePowerToysModule selectedItem = args.SelectedItem as OobePowerToysModule;
switch (selectedItem.Tag)
{
case "Overview": NavigationFrame.Navigate(typeof(OobeOverview)); break;
case "Awake": NavigationFrame.Navigate(typeof(OobeAwake)); break;
case "ColorPicker": NavigationFrame.Navigate(typeof(OobeColorPicker)); break;
case "FancyZones": NavigationFrame.Navigate(typeof(OobeFancyZones)); 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 "FileExplorer": NavigationFrame.Navigate(typeof(OobeFileExplorer)); break;
case "ShortcutGuide": NavigationFrame.Navigate(typeof(OobeShortcutGuide)); break;
case "VideoConference": NavigationFrame.Navigate(typeof(OobeVideoConference)); break;
case "MouseUtils": NavigationFrame.Navigate(typeof(OobeMouseUtils)); break;
}
}
public void UpdateUITheme()
{
switch (SettingsRepository<GeneralSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Theme.ToUpperInvariant())
{
case "LIGHT":
this.RequestedTheme = ElementTheme.Light;
break;
case "DARK":
this.RequestedTheme = ElementTheme.Dark;
break;
case "SYSTEM":
this.RequestedTheme = ElementTheme.Default;
break;
}
}
}
}

View file

@ -0,0 +1,32 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeShortcutGuide"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<TextBlock x:Uid="Oobe_HowToLaunch"
Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl x:Name="HotkeyControl" x:Uid="Oobe_ShortcutGuide_HowToLaunch" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="Launch_ShortcutGuide" Style="{StaticResource AccentButtonStyle}" Click="Start_ShortcutGuide_Click"/>
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_ShortcutGuide"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</controls:OOBEPageControl>
</Page>

View file

@ -0,0 +1,66 @@
// 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.Diagnostics;
using System.Globalization;
using System.IO;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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)PowerToysModulesEnum.ShortcutGuide]);
DataContext = ViewModel;
}
private void Start_ShortcutGuide_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
var executablePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\modules\ShortcutGuide\ShortcutGuide\PowerToys.ShortcutGuide.exe");
var id = Process.GetCurrentProcess().Id.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();
HotkeyControl.Keys = SettingsRepository<ShortcutGuideSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.OpenShortcutGuide.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View file

@ -0,0 +1,37 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Views.OobeVideoConference"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl ModuleTitle="{x:Bind ViewModel.ModuleName}"
ModuleImageSource="{x:Bind ViewModel.PreviewImageSource}"
ModuleDescription="{x:Bind ViewModel.Description}">
<controls:OOBEPageControl.ModuleContent>
<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="HotkeyVidControl" x:Uid="Oobe_VideoConference_ToggleVid" />
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_VideoConference_HowToLaunch" />
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
<Button x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click"/>
<HyperlinkButton NavigateUri="{x:Bind ViewModel.Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock x:Uid="LearnMore_VCM"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.ModuleContent>
</controls:OOBEPageControl>
</Page>

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 Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.WinUI3.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.WinUI3.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.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)PowerToysModulesEnum.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();
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,581 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)">
<Style x:Key="SettingButtonStyle" TargetType="Button" BasedOn="{StaticResource DefaultButtonStyle}" >
<Setter Property="BorderBrush" Value="{ThemeResource CardBorderBrush}" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Padding" Value="16,0,16,0" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
<Style x:Key="HyperlinkButtonStyle" TargetType="HyperlinkButton" >
</Style>
<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}" CornerRadius="4" Background="{TemplateBinding Background}">
<ContentPresenter x:Name="Text"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
FontWeight="SemiBold"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<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>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- This style overrides the default style so that all ToggleSwitches are right aligned, with the label on the left -->
<Style TargetType="ToggleSwitch">
<Setter Property="Foreground" Value="{ThemeResource ToggleSwitchContentForeground}" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="ManipulationMode" Value="System,TranslateX" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="-7,-3,-7,-3" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleSwitch">
<Grid
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}">
<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 Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Width" EnableDependentAnimation="True" >
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Height" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Width" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Height" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" 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 Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Width" EnableDependentAnimation="True" >
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Height" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Width" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Height" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" 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 Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Width" EnableDependentAnimation="True" >
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="17" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Height" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Width" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="17" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Height" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" 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 Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Width" EnableDependentAnimation="True" >
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlNormalAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn" Storyboard.TargetProperty="Height" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlNormalAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Width" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlNormalAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff" Storyboard.TargetProperty="Height" EnableDependentAnimation="True">
<SplineDoubleKeyFrame KeyTime="{StaticResource ControlNormalAnimationDuration}" KeySpline="{StaticResource ControlFastOutSlowInKeySpline}" Value="12" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ToggleStates">
<VisualStateGroup.Transitions>
<VisualTransition x:Name="DraggingToOnTransition"
From="Dragging"
To="On"
GeneratedDuration="0">
<Storyboard>
<RepositionThemeAnimation TargetName="SwitchKnob" FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobCurrentToOnOffset}" />
<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"
From="On"
To="Dragging"
GeneratedDuration="0">
<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"
From="Dragging"
To="Off"
GeneratedDuration="0">
<Storyboard>
<RepositionThemeAnimation TargetName="SwitchKnob" FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobCurrentToOffOffset}" />
<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"
From="On"
To="Off"
GeneratedDuration="0">
<Storyboard>
<RepositionThemeAnimation TargetName="SwitchKnob" FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobOnToOffOffset}" />
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="OffToOnTransition"
From="Off"
To="On"
GeneratedDuration="0">
<Storyboard>
<RepositionThemeAnimation TargetName="SwitchKnob" FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobOffToOnOffset}"/>
<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.TargetProperty="IsHitTestVisible" Storyboard.TargetName="OffContentPresenter">
<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.TargetProperty="IsHitTestVisible" Storyboard.TargetName="OnContentPresenter">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<x:Boolean>True</x:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentPresenter x:Name="HeaderContentPresenter"
x:DeferLoadStrategy="Lazy"
Grid.Row="0"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
Foreground="{ThemeResource ToggleSwitchHeaderForeground}"
IsHitTestVisible="False"
Margin="{ThemeResource ToggleSwitchTopHeaderMargin}"
TextWrapping="Wrap"
VerticalAlignment="Top"
Visibility="Collapsed"
AutomationProperties.AccessibilityView="Raw" />
<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"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
contract7NotPresent:CornerRadius="{StaticResource ControlCornerRadius}"
Control.IsTemplateFocusTarget="True"
Background="{ThemeResource ToggleSwitchContainerBackground}" />
<ContentPresenter x:Name="OffContentPresenter"
Grid.RowSpan="3"
Grid.Column="0"
Opacity="0"
Foreground="{TemplateBinding Foreground}"
IsHitTestVisible="False"
Content="{TemplateBinding OffContent}"
ContentTemplate="{TemplateBinding OffContentTemplate}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw" />
<ContentPresenter x:Name="OnContentPresenter"
Grid.RowSpan="3"
Grid.Column="0"
Opacity="0"
Foreground="{TemplateBinding Foreground}"
IsHitTestVisible="False"
Content="{TemplateBinding OnContent}"
ContentTemplate="{TemplateBinding OnContentTemplate}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw" />
<Rectangle x:Name="OuterBorder"
Grid.Row="1"
Grid.Column="2"
Height="20"
Width="40"
RadiusX="10"
RadiusY="10"
Fill="{ThemeResource ToggleSwitchFillOff}"
Stroke="{ThemeResource ToggleSwitchStrokeOff}"
StrokeThickness="{ThemeResource ToggleSwitchOuterBorderStrokeThickness}" />
<Rectangle x:Name="SwitchKnobBounds"
Grid.Row="1"
Height="20"
Width="40"
RadiusX="10"
RadiusY="10"
Grid.Column="2"
Fill="{ThemeResource ToggleSwitchFillOn}"
Stroke="{ThemeResource ToggleSwitchStrokeOn}"
StrokeThickness="{ThemeResource ToggleSwitchOnStrokeThickness}"
Opacity="0" />
<Grid x:Name="SwitchKnob"
Grid.Row="1"
Grid.Column="2"
HorizontalAlignment="Left"
Width="20"
Height="20">
<Border x:Name="SwitchKnobOn"
Background="{ThemeResource ToggleSwitchKnobFillOn}"
BorderBrush="{ThemeResource ToggleSwitchKnobStrokeOn}"
contract7Present:BackgroundSizing="OuterBorderEdge"
Width="12"
Height="12"
CornerRadius="7"
Grid.Column="2"
Opacity="0"
HorizontalAlignment="Center"
Margin="0,0,1,0"
RenderTransformOrigin="0.5, 0.5">
<Border.RenderTransform>
<CompositeTransform/>
</Border.RenderTransform>
</Border>
<Rectangle x:Name="SwitchKnobOff"
Fill="{ThemeResource ToggleSwitchKnobFillOff}"
Width="12"
Height="12"
RadiusX="7"
Grid.Column="2"
RadiusY="7"
HorizontalAlignment="Center"
Margin="-1,0,0,0"
RenderTransformOrigin="0.5, 0.5">
<Rectangle.RenderTransform>
<CompositeTransform/>
</Rectangle.RenderTransform>
</Rectangle>
<Grid.RenderTransform>
<TranslateTransform x:Name="KnobTranslateTransform" />
</Grid.RenderTransform>
</Grid>
<Thumb x:Name="SwitchThumb"
AutomationProperties.AccessibilityView="Raw"
Grid.RowSpan="3"
Grid.ColumnSpan="3">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Rectangle Fill="Transparent" />
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View file

@ -0,0 +1,23 @@
<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>
</ResourceDictionary>

View file

@ -0,0 +1,33 @@
<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">
<StaticResource x:Key="CardBackgroundBrush" ResourceKey="CardBackgroundFillColorDefaultBrush" />
<StaticResource x:Key="CardBorderBrush" ResourceKey="CardStrokeColorDefaultBrush" />
<StaticResource x:Key="CardPrimaryForegroundBrush" ResourceKey="TextFillColorPrimaryBrush" />
<SolidColorBrush x:Key="InfoBarInformationalSeverityBackgroundBrush" Color="#FF34424d"/>
<Color x:Key="InfoBarInformationalSeverityIconBackground">#FF5fb2f2</Color>
<Thickness x:Key="CardBorderThickness">1</Thickness>
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="CardBackgroundBrush" ResourceKey="CardBackgroundFillColorDefaultBrush" />
<StaticResource x:Key="CardBorderBrush" ResourceKey="CardStrokeColorDefaultBrush" />
<StaticResource x:Key="CardPrimaryForegroundBrush" ResourceKey="TextFillColorPrimaryBrush" />
<SolidColorBrush x:Key="InfoBarInformationalSeverityBackgroundBrush" Color="#FFd3e7f7"/>
<Color x:Key="InfoBarInformationalSeverityIconBackground">#FF0063b1</Color>
<Thickness x:Key="CardBorderThickness">1</Thickness>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<StaticResource x:Key="CardBackgroundBrush" ResourceKey="SystemColorButtonFaceColorBrush" />
<StaticResource x:Key="CardBorderBrush" ResourceKey="SystemColorButtonTextColorBrush" />
<StaticResource x:Key="CardPrimaryForegroundBrush" ResourceKey="SystemColorButtonTextColorBrush" />
<SolidColorBrush x:Key="InfoBarInformationalSeverityBackgroundBrush" Color="#FF34424d"/>
<Color x:Key="InfoBarInformationalSeverityIconBackground">#FF5fb2f2</Color>
<Thickness x:Key="CardBorderThickness">2</Thickness>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

View file

@ -0,0 +1,10 @@
<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:///Controls/Setting/Setting.xaml" />
<ResourceDictionary Source="ms-appx:///Controls/SettingsGroup/SettingsGroup.xaml" />
<ResourceDictionary Source="ms-appx:///Controls/IsEnabledTextBlock/IsEnabledTextBlock.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View file

@ -0,0 +1,49 @@
<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.WinUI3.Controls"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls">
<!-- Thickness -->
<Thickness x:Key="ExpanderContentPadding">0</Thickness>
<Thickness x:Key="ExpanderSettingMargin">56, 8, 40, 8</Thickness>
<SolidColorBrush x:Key="ExpanderChevronPointerOverBackground">Transparent</SolidColorBrush>
<!-- Styles -->
<!-- Setting used in a Expander header -->
<Style x:Key="ExpanderHeaderSettingStyle" TargetType="controls:Setting">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Padding" Value="0, 14, 0, 14" />
<Setter Property="Margin" Value="0"/>
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style>
<Thickness x:Key="ExpanderChevronMargin">0,0,8,0</Thickness>
<!-- Setting used in a Expander header -->
<Style x:Key="ExpanderContentSettingStyle" TargetType="controls:Setting">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0,1,0,0" />
<Setter Property="BorderBrush" Value="{ThemeResource CardBorderBrush}" />
<Setter Property="CornerRadius" Value="0" />
<Setter Property="Padding" Value="{StaticResource ExpanderSettingMargin}" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style>
<!-- Setting expander style -->
<Style x:Key="SettingExpanderStyle" TargetType="muxc:Expander">
<Setter Property="Background" Value="{ThemeResource CardBackgroundBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource CardBorderThickness}" />
<Setter Property="BorderBrush" Value="{ThemeResource CardBorderBrush}" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
<Style x:Key="ExpanderSeparatorStyle" TargetType="Rectangle">
<Setter Property="Height" Value="1"/>
<Setter Property="Stroke" Value="{ThemeResource CardBorderBrush}" />
</Style>
</ResourceDictionary>

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.Windows.Input;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.ViewModels.Commands
{
public class ButtonClickCommand : ICommand
{
private readonly Action _execute;
public ButtonClickCommand(Action execute)
{
_execute = execute;
}
// Occurs when changes occur that affect whether or not the command should execute.
public event EventHandler CanExecuteChanged;
// Defines the method that determines whether the command can execute in its current state.
public bool CanExecute(object parameter)
{
return true;
}
// Defines the method to be called when the command is invoked.
public void Execute(object parameter)
{
_execute();
}
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}

View file

@ -0,0 +1,139 @@
// 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.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Microsoft.PowerToys.Settings.UI.WinUI3.Helpers;
using Microsoft.PowerToys.Settings.UI.WinUI3.Services;
using Windows.System;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Navigation;
using WinUI = Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.ViewModels
{
public class ShellViewModel : Observable
{
private readonly KeyboardAccelerator altLeftKeyboardAccelerator = BuildKeyboardAccelerator(VirtualKey.Left, VirtualKeyModifiers.Menu);
private readonly KeyboardAccelerator backKeyboardAccelerator = BuildKeyboardAccelerator(VirtualKey.GoBack);
private bool isBackEnabled;
private IList<KeyboardAccelerator> keyboardAccelerators;
private WinUI.NavigationView navigationView;
private WinUI.NavigationViewItem selected;
private ICommand loadedCommand;
private ICommand itemInvokedCommand;
public bool IsBackEnabled
{
get { return isBackEnabled; }
set { Set(ref isBackEnabled, value); }
}
public bool IsVideoConferenceBuild
{
get
{
var mfHandle = NativeMethods.LoadLibrary("mf.dll");
bool mfAvailable = mfHandle != null;
if (mfAvailable)
{
NativeMethods.FreeLibrary(mfHandle);
}
return this != null && File.Exists("modules/VideoConference/VideoConferenceModule.dll") && mfAvailable;
}
}
public WinUI.NavigationViewItem Selected
{
get { return selected; }
set { Set(ref selected, value); }
}
public ICommand LoadedCommand => loadedCommand ?? (loadedCommand = new RelayCommand(OnLoaded));
public ICommand ItemInvokedCommand => itemInvokedCommand ?? (itemInvokedCommand = new RelayCommand<WinUI.NavigationViewItemInvokedEventArgs>(OnItemInvoked));
public ShellViewModel()
{
}
public void Initialize(Frame frame, WinUI.NavigationView navigationView, IList<KeyboardAccelerator> keyboardAccelerators)
{
this.navigationView = navigationView;
this.keyboardAccelerators = keyboardAccelerators;
NavigationService.Frame = frame;
NavigationService.NavigationFailed += Frame_NavigationFailed;
NavigationService.Navigated += Frame_Navigated;
this.navigationView.BackRequested += OnBackRequested;
}
private static KeyboardAccelerator BuildKeyboardAccelerator(VirtualKey key, VirtualKeyModifiers? modifiers = null)
{
var keyboardAccelerator = new KeyboardAccelerator() { Key = key };
if (modifiers.HasValue)
{
keyboardAccelerator.Modifiers = modifiers.Value;
}
keyboardAccelerator.Invoked += OnKeyboardAcceleratorInvoked;
return keyboardAccelerator;
}
private static void OnKeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
{
var result = NavigationService.GoBack();
args.Handled = result;
}
private async void OnLoaded()
{
// Keyboard accelerators are added here to avoid showing 'Alt + left' tooltip on the page.
// More info on tracking issue https://github.com/Microsoft/microsoft-ui-xaml/issues/8
keyboardAccelerators.Add(altLeftKeyboardAccelerator);
keyboardAccelerators.Add(backKeyboardAccelerator);
await Task.CompletedTask.ConfigureAwait(false);
}
private void OnItemInvoked(WinUI.NavigationViewItemInvokedEventArgs args)
{
var item = navigationView.MenuItems
.OfType<WinUI.NavigationViewItem>()
.First(menuItem => (string)menuItem.Content == (string)args.InvokedItem);
var pageType = item.GetValue(NavHelper.NavigateToProperty) as Type;
NavigationService.Navigate(pageType);
}
private void OnBackRequested(WinUI.NavigationView sender, WinUI.NavigationViewBackRequestedEventArgs args)
{
NavigationService.GoBack();
}
private void Frame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw e.Exception;
}
private void Frame_Navigated(object sender, NavigationEventArgs e)
{
IsBackEnabled = NavigationService.CanGoBack;
Selected = navigationView.MenuItems
.OfType<WinUI.NavigationViewItem>()
.FirstOrDefault(menuItem => IsMenuItemForPageType(menuItem, e.SourcePageType));
}
private static bool IsMenuItemForPageType(WinUI.NavigationViewItem menuItem, Type sourcePageType)
{
var pageType = menuItem.GetValue(NavHelper.NavigateToProperty) as Type;
return pageType == sourcePageType;
}
}
}

View file

@ -0,0 +1,87 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Views.AwakePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.WinUI3.Converters"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
mc:Ignorable="d"
AutomationProperties.LandmarkType="Main">
<Page.Resources>
<converters:AwakeModeToIntConverter x:Key="AwakeModeToIntConverter" />
</Page.Resources>
<controls:SettingsPageControl x:Uid="Awake" IsTabStop="False"
ModuleImageSource="ms-appx:///Assets/Modules/Awake.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<controls:Setting x:Uid="Awake_EnableAwake">
<controls:Setting.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsAwake.png" ShowAsMonochrome="False" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" HorizontalAlignment="Right"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:SettingsGroup x:Uid="Awake_Behavior_GroupSettings" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:Setting x:Uid="Awake_Mode" Icon="&#xEC4E;" >
<controls:Setting.ActionContent>
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.Mode, Mode=TwoWay, Converter={StaticResource AwakeModeToIntConverter}}">
<ComboBoxItem x:Uid="Awake_NoKeepAwake"/>
<ComboBoxItem x:Uid="Awake_IndefiniteKeepAwake"/>
<ComboBoxItem x:Uid="Awake_TemporaryKeepAwake"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="Awake_TimeBeforeAwake" Icon="&#xE916;" Visibility="{x:Bind ViewModel.IsTimeConfigurationEnabled, Mode=OneWay}">
<controls:Setting.ActionContent>
<StackPanel
Orientation="Horizontal">
<muxc:NumberBox x:Uid="Awake_TemporaryKeepAwake_Hours"
Value="{x:Bind ViewModel.Hours, Mode=TwoWay}"
Minimum="0"
SpinButtonPlacementMode="Compact"
HorizontalAlignment="Left"
Width="96"
SmallChange="1"
LargeChange="5"/>
<muxc:NumberBox x:Uid="Awake_TemporaryKeepAwake_Minutes"
Value="{x:Bind ViewModel.Minutes, Mode=TwoWay}"
Minimum="0"
SpinButtonPlacementMode="Compact"
Margin="8,0,0,0"
HorizontalAlignment="Left"
Width="96"
Maximum="60"
SmallChange="1"
LargeChange="5"/>
</StackPanel>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="Awake_EnableDisplayKeepAwake" Icon="&#xE7FB;">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.KeepDisplayOn, Mode=TwoWay}" />
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_Awake" Link="https://aka.ms/PowerToysOverview_Awake"/>
</controls:SettingsPageControl.PrimaryLinks>
<controls:SettingsPageControl.SecondaryLinks>
<controls:PageLink Text="Den Delimarsky's Awake" Link="https://Awake.den.dev"/>
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>

View file

@ -0,0 +1,23 @@
// 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.Library.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Views
{
public sealed partial class AwakePage : Page
{
private AwakeViewModel ViewModel { get; set; }
public AwakePage()
{
var settingsUtils = new SettingsUtils();
ViewModel = new AwakeViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<AwakeSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
InitializeComponent();
}
}
}

View file

@ -0,0 +1,158 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Views.ColorPickerPage"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:models="using:Microsoft.PowerToys.Settings.UI.Library"
mc:Ignorable="d"
x:Name="RootPage"
AutomationProperties.LandmarkType="Main">
<controls:SettingsPageControl x:Uid="ColorPicker"
ModuleImageSource="ms-appx:///Assets/Modules/ColorPicker.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical"
x:Name="ColorPickerView">
<controls:Setting x:Uid="ColorPicker_EnableColorPicker">
<controls:Setting.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsColorPicker.png" ShowAsMonochrome="False" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</controls:Setting.ActionContent>
</controls:Setting>
<controls:SettingsGroup x:Uid="Shortcut" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:Setting x:Uid="Activation_Shortcut" Icon="&#xEDA7;">
<controls:Setting.ActionContent>
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}"
HotkeySettings="{x:Bind Path=ViewModel.ActivationShortcut, Mode=TwoWay}"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="ColorPicker_ActivationAction" Icon="&#xEC4E;" >
<controls:Setting.ActionContent>
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.ActivationBehavior, Mode=TwoWay}" >
<ComboBoxItem x:Uid="EditorFirst"/>
<ComboBoxItem x:Uid="ColorPickerFirst"/>
<ComboBoxItem x:Uid="ColorPickerOnly"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="ColorFormats" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:Setting x:Uid="ColorPicker_CopiedColorRepresentation" Icon="&#xF0E3;">
<controls:Setting.ActionContent>
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}"
x:Name="ColorPicker_ComboBox"
HorizontalAlignment="Left"
DisplayMemberPath="Value"
ItemsSource="{Binding SelectableColorRepresentations}"
Loaded="ColorPicker_ComboBox_Loaded"
SelectedValue="{Binding SelectedColorRepresentationValue, Mode=TwoWay}"
SelectedValuePath="Key" />
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="ColorPicker_ShowColorName">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{Binding ShowColorName, Mode=TwoWay}" />
</controls:Setting.ActionContent>
</controls:Setting>
<!--
Disabling this until we have a safer way to reset cursor as
we can hit a state where the cursor doesn't reset
<CheckBox x:Uid="ColorPicker_ChangeCursor"
IsChecked="{Binding ChangeCursor, Mode=TwoWay}"
Margin="{StaticResource SmallTopMargin}"
IsEnabled="{Binding IsEnabled}"/>
-->
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="ColorPicker_Editor" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:Setting x:Name="ColorFormatsSetting" x:Uid="ColorPicker_ColorFormats" Icon="&#xE14C;"/>
<!-- Disabled reordering by dragging -->
<!-- CanReorderItems="True" AllowDrop="True" -->
<ListView ItemsSource="{Binding ColorFormats, Mode=TwoWay}"
AutomationProperties.Name="{Binding ElementName=ColorFormatsSetting, Path=Header}"
SelectionMode="None"
HorizontalAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:ColorFormatModel">
<Grid AutomationProperties.Name="{x:Bind Name}"
HorizontalAlignment="Stretch"
Background="{ThemeResource CardBackgroundBrush}"
BorderThickness="{ThemeResource CardBorderThickness}"
BorderBrush="{ThemeResource CardBorderBrush}"
CornerRadius="{ThemeResource ControlCornerRadius}"
Padding="0,0,16,0"
MinHeight="68">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock FontWeight="SemiBold"
FontSize="16"
Margin="56,8,0,0"
Text="{x:Bind Name}"/>
<TextBlock Style="{StaticResource SecondaryTextStyle}"
Text="{x:Bind Example}"
Grid.Row="1"
Margin="56,0,0,8"/>
<ToggleSwitch IsOn="{x:Bind IsShown, Mode=TwoWay}"
OnContent=""
OffContent=""
Grid.RowSpan="2"
x:Uid="Enable_ColorFormat"
AutomationProperties.HelpText="{x:Bind Name}"
HorizontalAlignment="Right"
Margin="0,0,56,0"/>
<Button Background="Transparent"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Grid.RowSpan="2"
x:Uid="More_Options_Button"
Content="&#xE10C;">
<Button.Flyout>
<MenuFlyout>
<MenuFlyoutItem IsEnabled="{x:Bind CanMoveUp}" Icon="Up" x:Uid="MoveUp" Click="ReorderButtonUp_Click"/>
<MenuFlyoutItem IsEnabled="{x:Bind CanMoveDown}" x:Uid="MoveDown" Click="ReorderButtonDown_Click">
<MenuFlyoutItem.Icon>
<FontIcon Glyph="&#xE1FD;" />
</MenuFlyoutItem.Icon>
</MenuFlyoutItem>
</MenuFlyout>
</Button.Flyout>
<ToolTipService.ToolTip>
<TextBlock x:Uid="More_Options_ButtonTooltip" />
</ToolTipService.ToolTip>
</Button>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_ColorPicker" Link="https://aka.ms/PowerToysOverview_ColorPicker"/>
</controls:SettingsPageControl.PrimaryLinks>
<controls:SettingsPageControl.SecondaryLinks>
<controls:PageLink Text="Martin Chrzan's Color Picker" Link="https://github.com/martinchrzan/ColorPicker/"/>
<controls:PageLink Text="Niels Laute's UX concept" Link="https://medium.com/@Niels9001/a-fluent-color-meter-for-powertoys-20407ededf0c"/>
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>

View file

@ -0,0 +1,81 @@
// 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.Library.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Views
{
public sealed partial class ColorPickerPage : Page
{
public ColorPickerViewModel ViewModel { get; set; }
public ColorPickerPage()
{
var settingsUtils = new SettingsUtils();
ViewModel = new ColorPickerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
InitializeComponent();
}
/// <summary>
/// Event is called when the <see cref="ComboBox"/> is completely loaded, inclusive the ItemSource
/// </summary>
/// <param name="sender">The sender of this event</param>
/// <param name="e">The arguments of this event</param>
private void ColorPicker_ComboBox_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
/**
* UWP hack
* because UWP load the bound ItemSource of the ComboBox asynchronous,
* so after InitializeComponent() the ItemSource is still empty and can't automatically select a entry.
* Selection via SelectedItem and SelectedValue is still not working too
*/
var index = 0;
foreach (var item in ViewModel.SelectableColorRepresentations)
{
if (item.Key == ViewModel.SelectedColorRepresentationValue)
{
break;
}
index++;
}
ColorPicker_ComboBox.SelectedIndex = index;
}
private void ReorderButtonUp_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
ColorFormatModel color = ((MenuFlyoutItem)sender).DataContext as ColorFormatModel;
if (color == null)
{
return;
}
var index = ViewModel.ColorFormats.IndexOf(color);
if (index > 0)
{
ViewModel.ColorFormats.Move(index, index - 1);
}
}
private void ReorderButtonDown_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
ColorFormatModel color = ((MenuFlyoutItem)sender).DataContext as ColorFormatModel;
if (color == null)
{
return;
}
var index = ViewModel.ColorFormats.IndexOf(color);
if (index < ViewModel.ColorFormats.Count - 1)
{
ViewModel.ColorFormats.Move(index, index + 1);
}
}
}
}

View file

@ -0,0 +1,287 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Views.FancyZonesPage"
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"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
mc:Ignorable="d"
AutomationProperties.LandmarkType="Main">
<Page.Resources>
<converters:BoolToObjectConverter x:Key="BoolToComboBoxIndexConverter" TrueValue="1" FalseValue="0"/>
<converters:StringFormatConverter x:Key="StringFormatConverter"/>
<converters:BoolToVisibilityConverter x:Key="FalseToVisibleConverter" TrueValue="Collapsed" FalseValue="Visible"/>
</Page.Resources>
<controls:SettingsPageControl x:Uid="FancyZones"
ModuleImageSource="ms-appx:///Assets/Modules/FancyZones.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<controls:Setting x:Uid="FancyZones_EnableToggleControl_HeaderText">
<controls:Setting.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFancyZones.png" ShowAsMonochrome="False" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:SettingsGroup x:Uid="FancyZones_Editor_GroupSettings" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<Button Style="{StaticResource SettingButtonStyle}" x:Uid="FancyZones_LaunchEditorButton_Accessible" Command="{x:Bind ViewModel.LaunchEditorEventHandler}">
<controls:Setting x:Uid="FancyZones_LaunchEditorButtonControl" Style="{StaticResource ExpanderHeaderSettingStyle}" Icon="&#xEB3C;">
<!--<controls:Setting.Icon>
<PathIcon Data="M45,48H25.5V45H45V25.5H25.5v-3H45V3H25.5V0H48V48ZM22.5,48H3V45H22.5V3H3V0H25.5V48ZM0,48V0H3V48Z"/>
</controls:Setting.Icon>-->
<controls:Setting.ActionContent>
<FontIcon Glyph="&#xE2B4;" FontFamily="{ThemeResource SymbolThemeFontFamily}" />
</controls:Setting.ActionContent>
</controls:Setting>
</Button>
<controls:Setting x:Uid="Activation_Shortcut" Icon="&#xEDA7;">
<controls:Setting.ActionContent>
<controls:ShortcutControl MinWidth="{StaticResource SettingActionControlMinWidth}"
HotkeySettings="{x:Bind Path=ViewModel.EditorHotkey, Mode=TwoWay}"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="FancyZones_UseCursorPosEditorStartupScreen" Icon="&#xE7F9;">
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.UseCursorPosEditorStartupScreen, Converter={StaticResource BoolToComboBoxIndexConverter}}" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="FancyZones_LaunchPositionScreen" />
<ComboBoxItem x:Uid="FancyZones_LaunchPositionMouse" />
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="FancyZones_Zones" x:Name="ZonesSettingsGroup" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="FancyZones_ZoneBehavior_GroupSettings" Icon="&#xE620;" Style="{StaticResource ExpanderHeaderSettingStyle}" />
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel>
<CheckBox x:Uid="FancyZones_ShiftDragCheckBoxControl_Header" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.ShiftDrag}" Margin="{StaticResource ExpanderSettingMargin}" />
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox x:Uid="FancyZones_MouseDragCheckBoxControl_Header" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.MouseSwitch}" Margin="{StaticResource ExpanderSettingMargin}" />
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox x:Uid="FancyZones_ShowZonesOnAllMonitorsCheckBoxControl" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.ShowOnAllMonitors}" Margin="{StaticResource ExpanderSettingMargin}" />
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<controls:CheckBoxWithDescriptionControl IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.SpanZonesAcrossMonitors}"
Margin="56, -2, 40, 14"
x:Uid="FancyZones_SpanZonesAcrossMonitors"/>
<controls:Setting x:Uid="FancyZones_OverlappingZones" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Path=ViewModel.OverlappingZonesAlgorithmIndex, Mode=TwoWay}" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="FancyZones_OverlappingZonesSmallest" />
<ComboBoxItem x:Uid="FancyZones_OverlappingZonesLargest" />
<ComboBoxItem x:Uid="FancyZones_OverlappingZonesPositional" />
<ComboBoxItem x:Uid="FancyZones_OverlappingZonesClosestCenter" />
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="FancyZones_Zone_Appearance" Icon="&#xE790;" Style="{StaticResource ExpanderHeaderSettingStyle}" >
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.SystemTheme, Converter={StaticResource BoolToComboBoxIndexConverter}}" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="FancyZones_Radio_Custom_Colors"/>
<ComboBoxItem x:Uid="FancyZones_Radio_Default_Theme"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel>
<StackPanel Visibility="{x:Bind Mode=OneWay, Path=ViewModel.SystemTheme, Converter={StaticResource FalseToVisibleConverter}}" >
<controls:Setting x:Uid="FancyZones_ZoneHighlightColor" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.ZoneHighlightColor, Mode=TwoWay}" />
</controls:Setting.ActionContent>
</controls:Setting>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<controls:Setting x:Uid="FancyZones_InActiveColor" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.ZoneInActiveColor, Mode=TwoWay}" />
</controls:Setting.ActionContent>
</controls:Setting>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<controls:Setting x:Uid="FancyZones_BorderColor" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.ZoneBorderColor, Mode=TwoWay}" />
</controls:Setting.ActionContent>
</controls:Setting>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
</StackPanel>
<controls:Setting x:Uid="FancyZones_HighlightOpacity" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<Slider Minimum="0"
Maximum="100"
MinWidth="{StaticResource SettingActionControlMinWidth}"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.HighlightOpacity}"
HorizontalAlignment="Right"/>
</controls:Setting.ActionContent>
</controls:Setting>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="FancyZones_Windows" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="FancyZones_WindowBehavior_GroupSettings" Icon="&#xE737;" Style="{StaticResource ExpanderHeaderSettingStyle}" />
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel>
<CheckBox x:Uid="FancyZones_DisplayChangeMoveWindowsCheckBoxControl" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.DisplayChangeMoveWindows}" Margin="{StaticResource ExpanderSettingMargin}"/>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox x:Uid="FancyZones_ZoneSetChangeMoveWindows" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.ZoneSetChangeMoveWindows}" Margin="{StaticResource ExpanderSettingMargin}"/>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox x:Uid="FancyZones_AppLastZoneMoveWindows" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.AppLastZoneMoveWindows}" Margin="{StaticResource ExpanderSettingMargin}"/>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox x:Uid="FancyZones_OpenWindowOnActiveMonitor" IsChecked="{ Binding Mode=TwoWay, Path=OpenWindowOnActiveMonitor}" Margin="{StaticResource ExpanderSettingMargin}"/>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox x:Uid="FancyZones_RestoreSize" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.RestoreSize}" Margin="{StaticResource ExpanderSettingMargin}"/>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox x:Uid="FancyZones_MakeDraggedWindowTransparentCheckBoxControl" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.MakeDraggedWindowsTransparent}" Margin="{StaticResource ExpanderSettingMargin}"/>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="FancyZones_WindowSwitching_GroupSettings" Icon="&#9112;" Style="{StaticResource ExpanderHeaderSettingStyle}">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.WindowSwitching}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel>
<controls:Setting x:Uid="FancyZones_HotkeyNextTabControl" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.WindowSwitchingCategoryEnabled}" Icon="&#9112;" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<controls:ShortcutControl HotkeySettings="{x:Bind Path=ViewModel.NextTabHotkey, Mode=TwoWay}" MinWidth="{StaticResource SettingActionControlMinWidth}"/>
</controls:Setting.ActionContent>
</controls:Setting>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<controls:Setting x:Uid="FancyZones_HotkeyPrevTabControl" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.WindowSwitchingCategoryEnabled}" Icon="&#9111;" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<controls:ShortcutControl HotkeySettings="{x:Bind Path=ViewModel.PrevTabHotkey, Mode=TwoWay}" MinWidth="{StaticResource SettingActionControlMinWidth}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="FancyZones_OverrideSnapHotkeys" Icon="&#xE145;" Style="{StaticResource ExpanderHeaderSettingStyle}">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.OverrideSnapHotkeys}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel>
<controls:Setting x:Uid="FancyZones_MoveWindow" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.SnapHotkeysCategoryEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.MoveWindowsBasedOnPosition, Converter={StaticResource BoolToComboBoxIndexConverter}}" MinHeight="56" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="FancyZones_MoveWindowLeftRightBasedOnZoneIndex_Accessible">
<StackPanel Orientation="Vertical" Spacing="4">
<controls:IsEnabledTextBlock x:Uid="FancyZones_MoveWindowLeftRightBasedOnZoneIndex"/>
<TextBlock FontFamily="{ThemeResource SymbolThemeFontFamily}" Style="{StaticResource SecondaryTextStyle}">
<Run x:Uid="FancyZones_MoveWindowLeftRightBasedOnZoneIndex_Description" />
</TextBlock>
</StackPanel>
</ComboBoxItem>
<ComboBoxItem x:Uid="FancyZones_MoveWindowBasedOnRelativePosition_Accessible">
<StackPanel Orientation="Vertical" Spacing="4">
<controls:IsEnabledTextBlock x:Uid="FancyZones_MoveWindowBasedOnRelativePosition"/>
<TextBlock FontFamily="{ThemeResource SymbolThemeFontFamily}" Style="{StaticResource SecondaryTextStyle}">
<Run x:Uid="FancyZones_MoveWindowBasedOnRelativePosition_Description" />
</TextBlock>
</StackPanel>
</ComboBoxItem>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox x:Uid="FancyZones_MoveWindowsAcrossAllMonitorsCheckBoxControl"
Margin="56,8,16,8"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.MoveWindowsAcrossMonitors}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.SnapHotkeysCategoryEnabled}"/>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="FancyZones_Layouts" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="FancyZones_QuickLayoutSwitch" Icon="&#xE737;" Style="{StaticResource ExpanderHeaderSettingStyle}" >
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.QuickLayoutSwitch}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel>
<CheckBox x:Uid="FancyZones_FlashZonesOnQuickSwitch" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.FlashZonesOnQuickSwitch}" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.QuickSwitchEnabled}" Margin="{StaticResource ExpanderSettingMargin}"/>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="ExcludedApps" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="FancyZones_ExcludeApps" Icon="&#xECE4;" Style="{StaticResource ExpanderHeaderSettingStyle}"/>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<TextBox x:Uid="FancyZones_ExcludeApps_TextBoxControl"
Margin="{StaticResource ExpanderSettingMargin}"
Text="{x:Bind Mode=TwoWay, Path=ViewModel.ExcludedApps, UpdateSourceTrigger=PropertyChanged}"
ScrollViewer.VerticalScrollBarVisibility ="Visible"
ScrollViewer.VerticalScrollMode="Enabled"
ScrollViewer.IsVerticalRailEnabled="True"
TextWrapping="Wrap"
AcceptsReturn="True"
MinWidth="240"
MinHeight="160" />
</controls:SettingExpander.Content>
</controls:SettingExpander>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_FancyZones" Link="https://aka.ms/PowerToysOverview_FancyZones"/>
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
</Page>

View file

@ -0,0 +1,28 @@
// 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.Library.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Views
{
public sealed partial class FancyZonesPage : Page
{
private FancyZonesViewModel ViewModel { get; set; }
public FancyZonesPage()
{
InitializeComponent();
var settingsUtils = new SettingsUtils();
ViewModel = new FancyZonesViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<FancyZonesSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
private void OpenColorsSettings_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
Helpers.StartProcessHelper.Start(Helpers.StartProcessHelper.ColorsSettings);
}
}
}

View file

@ -0,0 +1,243 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Views.GeneralPage"
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.WinUI3.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:localConverters="using:Microsoft.PowerToys.Settings.UI.WinUI3.Converters"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d"
AutomationProperties.LandmarkType="Main">
<Page.Resources>
<converters:BoolToVisibilityConverter x:Key="VisibleIfTrueConverter"/>
<converters:BoolNegationConverter x:Key="NegationConverter"/>
<localConverters:UpdateStateToBoolConverter x:Key="UpdateStateToBoolConverter" />
</Page.Resources>
<controls:SettingsPageControl x:Uid="General"
ModuleImageSource="ms-appx:///Assets/Modules/PT.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<controls:SettingsGroup x:Uid="General_Version" Margin="0,-32,0,0">
<controls:Setting Header="{Binding PowerToysVersion}" Icon="&#xE117;">
<controls:Setting.Description>
<StackPanel Orientation="Vertical">
<TextBlock Style="{StaticResource SecondaryTextStyle}">
<Run x:Uid="General_VersionLastChecked" />
<Run Text="{Binding UpdateCheckedDate, Mode=OneWay}"/>
</TextBlock>
<HyperlinkButton x:Uid="ReleaseNotes"
NavigateUri="https://github.com/microsoft/PowerToys/releases/"
Margin="0,2,0,0"/>
</StackPanel>
</controls:Setting.Description>
<controls:Setting.ActionContent>
<Grid Visibility="{Binding PowerToysUpdatingState, Mode=OneWay, Converter={StaticResource UpdateStateToBoolConverter}, ConverterParameter=UpToDate}">
<StackPanel Visibility="{Binding Mode=OneWay, Path=IsNewVersionDownloading, Converter={StaticResource VisibleIfTrueConverter}}"
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="18">
<muxc:ProgressRing Height="24"
Width="24"/>
<TextBlock x:Uid="General_CheckingForUpdates"
FontWeight="SemiBold"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</StackPanel>
<Button x:Uid="GeneralPage_CheckForUpdates"
Command="{Binding CheckForUpdatesEventHandler}"
IsEnabled="{Binding IsDownloadAllowed}"
Visibility="{Binding Mode=OneWay, Path=IsNewVersionDownloading, Converter={StaticResource NegationConverter}}"
HorizontalAlignment="Right"/>
</Grid>
</controls:Setting.ActionContent>
</controls:Setting>
<muxc:InfoBar x:Uid="General_UpToDate"
IsClosable="False"
Severity="Success"
IsTabStop="True"
IsOpen="{Binding IsNewVersionCheckedAndUpToDate, Mode=OneWay}"/>
<!-- New version available -->
<muxc:InfoBar x:Uid="General_NewVersionAvailable"
IsClosable="False"
Severity="Informational"
IsTabStop="True"
IsOpen="{Binding PowerToysUpdatingState, Mode=OneWay, Converter={StaticResource UpdateStateToBoolConverter}, ConverterParameter=ReadyToDownload}"
Message="{Binding PowerToysNewAvailableVersion, Mode=OneWay}">
<muxc:InfoBar.Content>
<StackPanel Spacing="16">
<Button x:Uid="General_DownloadAndInstall"
Command="{Binding UpdateNowButtonEventHandler}"
IsEnabled="{Binding IsDownloadAllowed, Mode=OneWay}"
Visibility="{Binding Mode=OneWay, Path=IsNewVersionDownloading, Converter={StaticResource NegationConverter}}"/>
<!-- In progress panel -->
<StackPanel Visibility="{Binding Mode=OneWay, Path=IsNewVersionDownloading, Converter={StaticResource VisibleIfTrueConverter}}"
Orientation="Horizontal"
Spacing="18"
Margin="0,0,0,16">
<muxc:ProgressRing Height="24"
Width="24"/>
<TextBlock x:Uid="General_Downloading"
FontWeight="SemiBold"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</StackPanel>
</StackPanel>
</muxc:InfoBar.Content>
<muxc:InfoBar.ActionButton>
<HyperlinkButton x:Uid="SeeWhatsNew"
Style="{StaticResource TextButtonStyle}"
NavigateUri="{Binding PowerToysNewAvailableVersionLink}"
HorizontalAlignment="Right" />
</muxc:InfoBar.ActionButton>
</muxc:InfoBar>
<!-- Ready to install -->
<muxc:InfoBar x:Uid="General_NewVersionReadyToInstall"
IsClosable="False"
Severity="Success"
IsTabStop="True"
IsOpen="{Binding PowerToysUpdatingState, Mode=OneWay, Converter={StaticResource UpdateStateToBoolConverter}, ConverterParameter=ReadyToInstall}"
Message="{Binding PowerToysNewAvailableVersion}">
<muxc:InfoBar.Content>
<StackPanel Spacing="16">
<Button x:Uid="General_InstallNow"
Command="{Binding UpdateNowButtonEventHandler}"
IsEnabled="{Binding IsDownloadAllowed, Mode=OneWay}"
Margin="0,0,0,16"/>
</StackPanel>
</muxc:InfoBar.Content>
<muxc:InfoBar.ActionButton>
<HyperlinkButton x:Uid="SeeWhatsNew"
Style="{StaticResource TextButtonStyle}"
NavigateUri="{Binding PowerToysNewAvailableVersionLink}"
HorizontalAlignment="Right" />
</muxc:InfoBar.ActionButton>
</muxc:InfoBar>
<!-- Install failed -->
<muxc:InfoBar x:Uid="General_FailedToDownloadTheNewVersion"
IsClosable="False"
Severity="Error"
IsTabStop="True"
IsOpen="{Binding PowerToysUpdatingState, Mode=OneWay, Converter={StaticResource UpdateStateToBoolConverter}, ConverterParameter=ErrorDownloading}"
Message="{Binding PowerToysNewAvailableVersion}">
<muxc:InfoBar.Content>
<StackPanel Spacing="16">
<Button x:Uid="General_TryAgainToDownloadAndInstall"
Command="{Binding UpdateNowButtonEventHandler}"
IsEnabled="{Binding IsDownloadAllowed, Mode=OneWay}"
Visibility="{Binding Mode=OneWay, Path=IsNewVersionDownloading, Converter={StaticResource NegationConverter}}"/>
<!-- In progress panel -->
<StackPanel Visibility="{Binding Mode=OneWay, Path=IsNewVersionDownloading, Converter={StaticResource VisibleIfTrueConverter}}"
Orientation="Horizontal"
Spacing="18"
Margin="0,0,0,16">
<muxc:ProgressRing Height="24"
Width="24"/>
<TextBlock x:Uid="General_Downloading"
FontWeight="SemiBold"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</StackPanel>
</StackPanel>
</muxc:InfoBar.Content>
<muxc:InfoBar.ActionButton>
<HyperlinkButton x:Uid="SeeWhatsNew"
NavigateUri="{Binding PowerToysNewAvailableVersionLink}"
HorizontalAlignment="Right"
Style="{StaticResource TextButtonStyle}"/>
</muxc:InfoBar.ActionButton>
</muxc:InfoBar>
<controls:Setting x:Uid="GeneralPage_ToggleSwitch_AutoDownloadUpdates"
Margin="0,-6,0,0"
Visibility="{Binding Mode=OneWay, Path=IsAdmin, Converter={StaticResource VisibleIfTrueConverter}}">
<ToggleSwitch IsOn="{Binding Mode=TwoWay, Path=AutoDownloadUpdates}"
IsEnabled="{Binding AutoUpdatesEnabled}" />
</controls:Setting>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="Admin_Mode">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="Admin_Mode" Icon="&#xE1A7;" Description="{Binding Mode=OneWay, Path=RunningAsText}" Style="{StaticResource ExpanderHeaderSettingStyle}">
<controls:Setting.ActionContent>
<Button x:Uid="GeneralPage_RestartAsAdmin_Button"
Command = "{Binding RestartElevatedButtonEventHandler}"
IsEnabled="{Binding Mode=OneWay, Path=IsAdminButtonEnabled}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel Orientation="Vertical">
<controls:Setting x:Uid="GeneralSettings_AlwaysRunAsAdminText" IsEnabled="{Binding Mode=OneWay, Path=IsElevated}" Style="{StaticResource ExpanderContentSettingStyle}">
<controls:Setting.Description>
<HyperlinkButton NavigateUri="https://aka.ms/powertoysDetectedElevatedHelp"
x:Uid="GeneralPage_ToggleSwitch_AlwaysRunElevated_Link"/>
</controls:Setting.Description>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{Binding Mode=TwoWay, Path=RunElevated}"/>
</controls:Setting.ActionContent>
</controls:Setting>
<muxc:InfoBar x:Uid="General_RunAsAdminRequired"
Severity="Warning"
IsTabStop="True"
IsClosable="False"
IsOpen="{Binding Mode=OneWay, Path=IsElevated, Converter={StaticResource NegationConverter}}"/>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
</controls:SettingsGroup>
<controls:SettingsGroup IsEnabled="True" x:Uid="ShortcutGuide_Appearance_Behavior">
<controls:Setting x:Uid="ColorModeHeader" Icon="&#xE790;">
<controls:Setting.Description>
<HyperlinkButton Click="OpenColorsSettings_Click"
x:Uid="Windows_Color_Settings"/>
</controls:Setting.Description>
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.ThemeIndex}" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="Radio_Theme_Dark"/>
<ComboBoxItem x:Uid="Radio_Theme_Light"/>
<ComboBoxItem x:Uid="Radio_Theme_Default"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="GeneralPage_RunAtStartUp">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{Binding Mode=TwoWay, Path=Startup}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="GeneralPage_Documentation" Link="https://aka.ms/PowerToysOverview"/>
<controls:PageLink x:Uid="General_Repository" Link="https://aka.ms/powertoys"/>
<controls:PageLink x:Uid="GeneralPage_ReportAbug" Link="https://aka.ms/powerToysReportBug"/>
<controls:PageLink x:Uid="GeneralPage_RequestAFeature_URL" Link="https://aka.ms/powerToysRequestFeature"/>
</controls:SettingsPageControl.PrimaryLinks>
<controls:SettingsPageControl.SecondaryLinks>
<controls:PageLink x:Uid="GeneralPage_PrivacyStatement_URL" Link="http://go.microsoft.com/fwlink/?LinkId=521839"/>
<controls:PageLink x:Uid="OpenSource_Notice" Link="https://github.com/microsoft/PowerToys/blob/main/NOTICE.md"/>
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>

View file

@ -0,0 +1,87 @@
// 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.CodeAnalysis;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
using Windows.ApplicationModel.Resources;
using Windows.UI.Core;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Views
{
/// <summary>
/// General Settings Page.
/// </summary>
public sealed partial class GeneralPage : Page
{
/// <summary>
/// Gets or sets view model.
/// </summary>
public GeneralViewModel ViewModel { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="GeneralPage"/> class.
/// General Settings page constructor.
/// </summary>
[SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Exceptions from the IPC response handler should be caught and logged.")]
public GeneralPage()
{
InitializeComponent();
// Load string resources
ResourceLoader loader = ResourceLoader.GetForViewIndependentUse();
var settingsUtils = new SettingsUtils();
Action stateUpdatingAction = async () =>
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, ViewModel.RefreshUpdatingState);
};
ViewModel = new GeneralViewModel(
SettingsRepository<GeneralSettings>.GetInstance(settingsUtils),
loader.GetString("GeneralSettings_RunningAsAdminText"),
loader.GetString("GeneralSettings_RunningAsUserText"),
ShellPage.IsElevated,
ShellPage.IsUserAnAdmin,
UpdateUIThemeMethod,
ShellPage.SendDefaultIPCMessage,
ShellPage.SendRestartAdminIPCMessage,
ShellPage.SendCheckForUpdatesIPCMessage,
string.Empty,
stateUpdatingAction);
DataContext = ViewModel;
}
public static int UpdateUIThemeMethod(string themeName)
{
switch (themeName?.ToUpperInvariant())
{
case "LIGHT":
ShellPage.ShellHandler.RequestedTheme = ElementTheme.Light;
break;
case "DARK":
ShellPage.ShellHandler.RequestedTheme = ElementTheme.Dark;
break;
case "SYSTEM":
ShellPage.ShellHandler.RequestedTheme = ElementTheme.Default;
break;
default:
Logger.LogError($"Unexpected theme name: {themeName}");
break;
}
return 0;
}
private void OpenColorsSettings_Click(object sender, RoutedEventArgs e)
{
Helpers.StartProcessHelper.Start(Helpers.StartProcessHelper.ColorsSettings);
}
}
}

View file

@ -0,0 +1,282 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Views.ImageResizerPage"
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.WinUI3.Controls"
xmlns:models="using:Microsoft.PowerToys.Settings.UI.Library"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.WinUI3.Converters"
xmlns:toolkitconverters="using:CommunityToolkit.WinUI.UI.Converters"
mc:Ignorable="d"
AutomationProperties.LandmarkType="Main" x:Name="RootPage">
<Page.Resources>
<converters:ImageResizerFitToStringConverter x:Key="ImageResizerFitToStringConverter" />
<converters:ImageResizerUnitToStringConverter x:Key="ImageResizerUnitToStringConverter" />
<toolkitconverters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" TrueValue="Visible" FalseValue="Collapsed" />
<toolkitconverters:BoolToObjectConverter x:Key="BoolToComboBoxIndexConverter" TrueValue="0" FalseValue="1"/>
</Page.Resources>
<controls:SettingsPageControl x:Uid="ImageResizer"
ModuleImageSource="ms-appx:///Assets/Modules/ImageResizer.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel>
<controls:Setting x:Uid="ImageResizer_EnableToggle">
<controls:Setting.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsImageResizer.png" ShowAsMonochrome="False" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</controls:Setting.ActionContent>
</controls:Setting>
<controls:SettingsGroup x:Uid="ImageResizer_CustomSizes" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:Setting x:Uid="ImageResizer_Presets" Icon="&#xE2B2;">
<controls:Setting.ActionContent>
<Button x:Uid="ImageResizer_AddSizeButton" Click="AddSizeButton_Click" Style="{ThemeResource AccentButtonStyle}" />
</controls:Setting.ActionContent>
</controls:Setting>
<ListView x:Name="ImagesSizesListView"
x:Uid="ImagesSizesListView"
ItemsSource="{x:Bind ViewModel.Sizes, Mode=TwoWay}"
SelectionMode="None"
ContainerContentChanging="ImagesSizesListView_ContainerContentChanging">
<ListView.ItemTemplate>
<DataTemplate x:Name="SingleLineDataTemplate" x:DataType="models:ImageSize">
<Grid AutomationProperties.Name="{x:Bind Name, Mode=OneWay}"
HorizontalAlignment="Stretch"
Background="{ThemeResource CardBackgroundBrush}"
BorderThickness="{ThemeResource CardBorderThickness}"
BorderBrush="{ThemeResource CardBorderBrush}"
CornerRadius="{ThemeResource ControlCornerRadius}"
Padding="0,0,16,0"
MinHeight="68">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="56" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Grid.Column="1" Margin="0,0,16,0">
<TextBlock Text="{x:Bind Name, Mode=OneWay}" FontWeight="SemiBold"
FontSize="16"/>
<StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1" Margin="0,4,0,0">
<TextBlock Text="{x:Bind Fit, Mode=OneWay, Converter={StaticResource ImageResizerFitToStringConverter}}" Style="{ThemeResource SecondaryTextStyle}" Margin="0,0,4,0"/>
<TextBlock Text="{x:Bind Width, Mode=OneWay}" FontWeight="SemiBold" Margin="0,0,4,0" Style="{ThemeResource SecondaryTextStyle}"/>
<TextBlock Text="&#xE947;" FontFamily="{ThemeResource SymbolThemeFontFamily}" FontSize="10" AutomationProperties.AccessibilityView="Raw" Visibility="{x:Bind Path=EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" Foreground="{ThemeResource SystemBaseMediumColor}" Margin="0,5,4,0" Style="{ThemeResource SecondaryTextStyle}"/>
<TextBlock Text="{x:Bind Height, Mode=OneWay}" Visibility="{x:Bind Path=EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" FontWeight="SemiBold" Margin="0,0,4,0" Style="{ThemeResource SecondaryTextStyle}"/>
<TextBlock Text="{x:Bind Unit, Mode=OneWay, Converter={StaticResource ImageResizerUnitToStringConverter},ConverterParameter=ToLower}" Foreground="{ThemeResource SystemBaseMediumColor}" Margin="0,0,4,0" Style="{ThemeResource SecondaryTextStyle}"/>
</StackPanel>
</StackPanel>
<StackPanel Spacing="8" HorizontalAlignment="Right" Grid.Column="2" Orientation="Horizontal">
<Button
x:Uid="EditButton"
Background="Transparent"
FontFamily="Segoe MDL2 Assets"
Width="40"
Height="36"
Content="&#xE70F;">
<ToolTipService.ToolTip>
<TextBlock x:Uid="EditTooltip"/>
</ToolTipService.ToolTip>
<Button.Flyout>
<Flyout>
<StackPanel Spacing="16" Margin="0,12,0,0">
<TextBox
x:Uid="ImageResizer_Name"
Text="{x:Bind Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Width="240"
HorizontalAlignment="Left"/>
<ComboBox
x:Uid="ImageResizer_Fit"
SelectedIndex="{x:Bind Path=Fit, Mode=TwoWay}"
Width="240"
HorizontalAlignment="Left">
<ComboBoxItem x:Uid="ImageResizer_Sizes_Fit_Fill" />
<ComboBoxItem x:Uid="ImageResizer_Sizes_Fit_Fit" />
<ComboBoxItem x:Uid="ImageResizer_Sizes_Fit_Stretch" />
</ComboBox>
<StackPanel Spacing="8" Orientation="Horizontal">
<muxc:NumberBox
x:Uid="ImageResizer_Width"
Value="{x:Bind Path=Width, Mode=TwoWay}"
Minimum="0"
Width="116"
SpinButtonPlacementMode="Compact"/>
<muxc:NumberBox
x:Uid="ImageResizer_Height"
Value="{x:Bind Path=Height, Mode=TwoWay}"
Width="116"
Minimum="0"
SpinButtonPlacementMode="Compact"
Visibility="{x:Bind Path=EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"/>
</StackPanel>
<ComboBox x:Uid="ImageResizer_Size"
SelectedIndex="{Binding Path=Unit, Mode=TwoWay}"
Width="240"
Margin="0,0,0,24">
<ComboBoxItem x:Uid="ImageResizer_Sizes_Units_CM" />
<ComboBoxItem x:Uid="ImageResizer_Sizes_Units_Inches" />
<ComboBoxItem x:Uid="ImageResizer_Sizes_Units_Percent" />
<ComboBoxItem x:Uid="ImageResizer_Sizes_Units_Pixels" />
</ComboBox>
</StackPanel>
</Flyout>
</Button.Flyout>
</Button>
<Button x:Name="RemoveButton"
x:Uid="RemoveButton"
Background="Transparent"
FontFamily="Segoe MDL2 Assets"
Width="40"
Height="36"
Content="&#xE74D;"
Click="DeleteCustomSize"
CommandParameter="{Binding Id}">
<ToolTipService.ToolTip>
<TextBlock x:Uid="RemoveTooltip"/>
</ToolTipService.ToolTip>
</Button>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="Encoding" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:Setting x:Uid="ImageResizer_FallBackEncoderText">
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Path=ViewModel.Encoder, Mode=TwoWay}"
MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="ImageResizer_FallbackEncoder_PNG" />
<ComboBoxItem x:Uid="ImageResizer_FallbackEncoder_BMP" />
<ComboBoxItem x:Uid="ImageResizer_FallbackEncoder_JPEG" />
<ComboBoxItem x:Uid="ImageResizer_FallbackEncoder_TIFF" />
<ComboBoxItem x:Uid="ImageResizer_FallbackEncoder_WMPhoto" />
<ComboBoxItem x:Uid="ImageResizer_FallbackEncoder_GIF" />
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="ImageResizer_Encoding">
<controls:Setting.ActionContent>
<Slider
Minimum="0"
Maximum="100"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.JPEGQualityLevel}"
MinWidth="{StaticResource SettingActionControlMinWidth}"
HorizontalAlignment="Right"
/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="ImageResizer_PNGInterlacing">
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.PngInterlaceOption}" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="Default"/>
<ComboBoxItem x:Uid="On"/>
<ComboBoxItem x:Uid="Off"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="ImageResizer_TIFFCompression">
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.TiffCompressOption}" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="ImageResizer_ENCODER_TIFF_Default"/>
<ComboBoxItem x:Uid="ImageResizer_ENCODER_TIFF_None"/>
<ComboBoxItem x:Uid="ImageResizer_ENCODER_TIFF_CCITT3"/>
<ComboBoxItem x:Uid="ImageResizer_ENCODER_TIFF_CCITT4"/>
<ComboBoxItem x:Uid="ImageResizer_ENCODER_TIFF_LZW"/>
<ComboBoxItem x:Uid="ImageResizer_ENCODER_TIFF_RLE"/>
<ComboBoxItem x:Uid="ImageResizer_ENCODER_TIFF_Zip"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="File" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:Setting x:Uid="ImageResizer_FilenameFormatHeader">
<controls:Setting.ActionContent>
<StackPanel Spacing="4" Orientation="Horizontal">
<TextBox Text="{x:Bind Mode=TwoWay, Path=ViewModel.FileName}"
HorizontalAlignment="Right"
MinWidth="{StaticResource SettingActionControlMinWidth}"
x:Uid="ImageResizer_FilenameFormatPlaceholder"/>
<Button Content="&#xE946;" x:Uid="ImageResizer_FilenameParameters" Height="32" FontFamily="{ThemeResource SymbolThemeFontFamily}">
<Button.Flyout>
<Flyout>
<TextBlock x:Name="FileFormatTextBlock">
<Run x:Uid="ImageResizer_FileFormatDescription"/>
<LineBreak/>
<LineBreak/>
<Run Text="%1" FontWeight="Bold" />
<Run Text=" - "/>
<Run x:Uid="ImageResizer_Formatting_Filename" />
<LineBreak/>
<Run Text="%2" FontWeight="Bold" />
<Run Text=" - "/>
<Run x:Uid="ImageResizer_Formatting_Sizename"/>
<LineBreak/>
<Run Text="%3" FontWeight="Bold" />
<Run Text=" - "/>
<Run x:Uid="ImageResizer_Formatting_SelectedWidth"/>
<LineBreak/>
<Run Text="%4" FontWeight="Bold" />
<Run Text=" - "/>
<Run x:Uid="ImageResizer_Formatting_SelectedHeight"/>
<LineBreak/>
<Run Text="%5" FontWeight="Bold" />
<Run Text=" - "/>
<Run x:Uid="ImageResizer_Formatting_ActualWidth"/>
<LineBreak/>
<Run Text="%6" FontWeight="Bold" />
<Run Text=" - "/>
<Run x:Uid="ImageResizer_Formatting_ActualHeight"/>
</TextBlock>
</Flyout>
</Button.Flyout>
</Button>
</StackPanel>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="ImageResizer_FileModifiedDate">
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.KeepDateModified, Converter={StaticResource BoolToComboBoxIndexConverter}}" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="ImageResizer_UseOriginalDate"/>
<ComboBoxItem x:Uid="ImageResizer_UseResizeDate"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_ImageResizer" Link="https://aka.ms/PowerToysOverview_ImageResizer"/>
</controls:SettingsPageControl.PrimaryLinks>
<controls:SettingsPageControl.SecondaryLinks>
<controls:PageLink Text="Brice Lambson's ImageResizer" Link="https://github.com/bricelam/ImageResizer/"/>
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>

View file

@ -0,0 +1,98 @@
// 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.CodeAnalysis;
using System.Globalization;
using System.Linq;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
using Windows.ApplicationModel.Resources;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Views
{
public sealed partial class ImageResizerPage : Page
{
public ImageResizerViewModel ViewModel { get; set; }
public ImageResizerPage()
{
InitializeComponent();
var settingsUtils = new SettingsUtils();
//TODO(stefan)
//var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
Func<string, string> loader = (string name) =>
{
//return resourceLoader.GetString(name);
return "TODO(stefan)";
};
ViewModel = new ImageResizerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, loader);
DataContext = ViewModel;
}
public async void DeleteCustomSize(object sender, RoutedEventArgs e)
{
Button deleteRowButton = (Button)sender;
if (deleteRowButton != null)
{
ImageSize x = (ImageSize)deleteRowButton.DataContext;
ResourceLoader resourceLoader = ResourceLoader.GetForCurrentView();
ContentDialog dialog = new ContentDialog();
dialog.XamlRoot = RootPage.XamlRoot;
dialog.Title = x.Name;
dialog.PrimaryButtonText = resourceLoader.GetString("Yes");
dialog.CloseButtonText = resourceLoader.GetString("No");
dialog.DefaultButton = ContentDialogButton.Primary;
dialog.Content = new TextBlock() { Text = resourceLoader.GetString("Delete_Dialog_Description") };
dialog.PrimaryButtonClick += (s, args) =>
{
// Using InvariantCulture since this is internal and expected to be numerical
bool success = int.TryParse(deleteRowButton?.CommandParameter?.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out int rowNum);
if (success)
{
ViewModel.DeleteImageSize(rowNum);
}
else
{
Logger.LogError("Failed to delete custom image size.");
}
};
var result = await dialog.ShowAsync();
}
}
[SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "JSON exceptions from saving new settings should be caught and logged.")]
private void AddSizeButton_Click(object sender, RoutedEventArgs e)
{
try
{
ViewModel.AddRow(ResourceLoader.GetForCurrentView().GetString("ImageResizer_DefaultSize_NewSizePrefix"));
}
catch (Exception ex)
{
Logger.LogError("Exception encountered when adding a new image size.", ex);
}
}
[SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "Params are required for event handler signature requirements.")]
private void ImagesSizesListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (ViewModel.IsListViewFocusRequested)
{
// Set focus to the last item in the ListView
int size = ImagesSizesListView.Items.Count;
((ListViewItem)ImagesSizesListView.ContainerFromIndex(size - 1)).Focus(FocusState.Programmatic);
// Reset the focus requested flag
ViewModel.IsListViewFocusRequested = false;
}
}
}
}

View file

@ -0,0 +1,205 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Views.KeyboardManagerPage"
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.WinUI3.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:Lib="using:Microsoft.PowerToys.Settings.UI.Library"
mc:Ignorable="d"
AutomationProperties.LandmarkType="Main">
<Page.Resources>
<local:VisibleIfNotEmpty x:Key="visibleIfNotEmptyConverter" />
<Style TargetType="ListViewItem" x:Name="KeysListViewContainerStyle">
<Setter Property="IsTabStop" Value="False"/>
</Style>
<DataTemplate x:Key="OriginalKeyTemplate" x:DataType="x:String">
<controls:KeyVisual Content="{Binding}" VisualType="SmallOutline" />
</DataTemplate>
<DataTemplate x:Key="RemappedKeyTemplate" x:DataType="x:String">
<controls:KeyVisual Content="{Binding}" VisualType="Small" />
</DataTemplate>
<!--<DataTemplate x:Name="KeysListViewTemplate" x:DataType="Lib:KeysDataModel">
<StackPanel
Name="KeyboardManager_RemappedKeysListItem"
x:Uid="KeyboardManager_RemappedKeysListItem"
Orientation="Horizontal"
Height="56">
</StackPanel>
</DataTemplate>-->
<!--<DataTemplate x:Name="ShortcutKeysListViewTemplate" x:DataType="Lib:AppSpecificKeysDataModel">
<StackPanel
Name="KeyboardManager_RemappedShortcutsListItem"
x:Uid="KeyboardManager_RemappedShortcutsListItem"
Orientation="Horizontal"
Height="56">
</DataTemplate>-->
</Page.Resources>
<controls:SettingsPageControl x:Uid="KeyboardManager"
ModuleImageSource="ms-appx:///Assets/Modules/KBM.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<controls:Setting x:Uid="KeyboardManager_EnableToggle">
<controls:Setting.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsKeyboardManager.png" ShowAsMonochrome="False" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Path=ViewModel.Enabled, Mode=TwoWay}" />
</controls:Setting.ActionContent>
<controls:Setting.Description>
<HyperlinkButton NavigateUri="https://aka.ms/powerToysCannotRemapKeys">
<TextBlock x:Uid="KBM_KeysCannotBeRemapped" FontWeight="SemiBold" />
</HyperlinkButton>
</controls:Setting.Description>
</controls:Setting>
<controls:SettingsGroup x:Uid="KeyboardManager_Keys" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.Enabled}">
<Button x:Uid="KeyboardManager_RemapKeyboardButton_Accessible" Style="{StaticResource SettingButtonStyle}" Command="{Binding Path=RemapKeyboardCommand}">
<controls:Setting x:Uid="KeyboardManager_RemapKeyboardButton" Style="{StaticResource ExpanderHeaderSettingStyle}" Icon="&#xE92E;">
<controls:Setting.ActionContent>
<FontIcon Glyph="&#xE8A7;" FontFamily="{ThemeResource SymbolThemeFontFamily}" />
</controls:Setting.ActionContent>
</controls:Setting>
</Button>
<ListView x:Name="RemapKeysList"
x:Uid="RemapKeysList"
ItemsSource="{x:Bind Path=ViewModel.RemapKeys, Mode=OneWay}"
SelectionMode="None"
IsSwipeEnabled="False"
Visibility="{x:Bind Path=ViewModel.RemapKeys, Mode=OneWay, Converter={StaticResource visibleIfNotEmptyConverter}}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="Lib:KeysDataModel">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Stretch"
Background="{ThemeResource CardBackgroundBrush}"
BorderThickness="{ThemeResource CardBorderThickness}"
BorderBrush="{ThemeResource CardBorderBrush}"
CornerRadius="{ThemeResource ControlCornerRadius}"
MinHeight="68">
<ItemsControl Margin="52,0,0,0"
ItemsSource="{x:Bind GetMappedOriginalKeys()}"
ItemTemplate="{StaticResource OriginalKeyTemplate}"
IsTabStop="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<TextBlock Text="to"
Style="{StaticResource SecondaryTextStyle}"
VerticalAlignment="Center"
Margin="8,0,8,0"/>
<ItemsControl Name="KeyboardManager_RemappedTo"
x:Uid="KeyboardManager_RemappedTo"
ItemsSource="{x:Bind GetMappedNewRemapKeys()}"
ItemTemplate="{StaticResource RemappedKeyTemplate}"
IsTabStop="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="KeyboardManager_Shortcuts" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.Enabled}">
<Button x:Uid="KeyboardManager_RemapShortcutsButton_Accessible" Style="{StaticResource SettingButtonStyle}" Command="{Binding Path=EditShortcutCommand}">
<controls:Setting x:Uid="KeyboardManager_RemapShortcutsButton" Style="{StaticResource ExpanderHeaderSettingStyle}" Icon="&#xE92E;">
<controls:Setting.ActionContent>
<FontIcon Glyph="&#xE8A7;" FontFamily="{ThemeResource SymbolThemeFontFamily}" />
</controls:Setting.ActionContent>
</controls:Setting>
</Button>
<ListView x:Name="RemapShortcutsList"
x:Uid="RemapShortcutsList"
ItemsSource="{x:Bind Path=ViewModel.RemapShortcuts, Mode=OneWay}"
SelectionMode="None"
IsSwipeEnabled="False"
Visibility="{x:Bind Path=ViewModel.RemapShortcuts, Mode=OneWay, Converter={StaticResource visibleIfNotEmptyConverter}}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="Lib:AppSpecificKeysDataModel">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Stretch"
Background="{ThemeResource CardBackgroundBrush}"
BorderThickness="{ThemeResource CardBorderThickness}"
BorderBrush="{ThemeResource CardBorderBrush}"
CornerRadius="{ThemeResource ControlCornerRadius}"
MinHeight="68">
<ItemsControl Margin="52,0,0,0"
ItemsSource="{x:Bind GetMappedOriginalKeys()}"
ItemTemplate="{StaticResource OriginalKeyTemplate}"
IsTabStop="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<TextBlock x:Uid="To"
Style="{StaticResource SecondaryTextStyle}"
VerticalAlignment="Center"
Margin="8,0,8,0"/>
<ItemsControl Name="KeyboardManager_RemappedTo"
x:Uid="KeyboardManager_RemappedTo"
ItemsSource="{x:Bind GetMappedNewRemapKeys()}"
ItemTemplate="{StaticResource RemappedKeyTemplate}"
IsTabStop="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<StackPanel Orientation="Horizontal">
<Border VerticalAlignment="Center"
Padding="12,4,12,6"
Margin="16,0,0,0"
CornerRadius="12">
<Border.Background>
<SolidColorBrush Color="{ThemeResource SystemAccentColorLight3}"
Opacity="0.3"/>
</Border.Background>
<TextBlock Text="{x:Bind TargetApp}"
Foreground="{ThemeResource SystemAccentColorDark1}"
FontWeight="SemiBold"
FontSize="12" />
</Border>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_KBM" Link="https://aka.ms/PowerToysOverview_KeyboardManager"/>
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
</Page>

View file

@ -0,0 +1,91 @@
// 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.Globalization;
using System.IO.Abstractions;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
using Windows.System;
using Windows.UI.Core;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class KeyboardManagerPage : Page
{
private const string PowerToyName = "Keyboard Manager";
private readonly CoreDispatcher dispatcher;
private readonly IFileSystemWatcher watcher;
public KeyboardManagerViewModel ViewModel { get; }
public KeyboardManagerPage()
{
dispatcher = Window.Current.Dispatcher;
var settingsUtils = new SettingsUtils();
ViewModel = new KeyboardManagerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, FilterRemapKeysList);
watcher = Helper.GetFileWatcher(
PowerToyName,
ViewModel.Settings.Properties.ActiveConfiguration.Value + ".json",
OnConfigFileUpdate);
InitializeComponent();
DataContext = ViewModel;
}
private async void OnConfigFileUpdate()
{
// Note: FileSystemWatcher raise notification multiple times for single update operation.
// Todo: Handle duplicate events either by somehow suppress them or re-read the configuration everytime since we will be updating the UI only if something is changed.
if (ViewModel.LoadProfile())
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
ViewModel.NotifyFileChanged();
});
}
}
private static void CombineRemappings(List<KeysDataModel> remapKeysList, uint leftKey, uint rightKey, uint combinedKey)
{
// Using InvariantCulture for keys as they are internally represented as numerical values
KeysDataModel firstRemap = remapKeysList.Find(x => uint.Parse(x.OriginalKeys, CultureInfo.InvariantCulture) == leftKey);
KeysDataModel secondRemap = remapKeysList.Find(x => uint.Parse(x.OriginalKeys, CultureInfo.InvariantCulture) == rightKey);
if (firstRemap != null && secondRemap != null)
{
if (firstRemap.NewRemapKeys == secondRemap.NewRemapKeys)
{
KeysDataModel combinedRemap = new KeysDataModel
{
OriginalKeys = combinedKey.ToString(CultureInfo.InvariantCulture),
NewRemapKeys = firstRemap.NewRemapKeys,
};
remapKeysList.Insert(remapKeysList.IndexOf(firstRemap), combinedRemap);
remapKeysList.Remove(firstRemap);
remapKeysList.Remove(secondRemap);
}
}
}
private int FilterRemapKeysList(List<KeysDataModel> remapKeysList)
{
CombineRemappings(remapKeysList, (uint)VirtualKey.LeftControl, (uint)VirtualKey.RightControl, (uint)VirtualKey.Control);
CombineRemappings(remapKeysList, (uint)VirtualKey.LeftMenu, (uint)VirtualKey.RightMenu, (uint)VirtualKey.Menu);
CombineRemappings(remapKeysList, (uint)VirtualKey.LeftShift, (uint)VirtualKey.RightShift, (uint)VirtualKey.Shift);
CombineRemappings(remapKeysList, (uint)VirtualKey.LeftWindows, (uint)VirtualKey.RightWindows, Helper.VirtualKeyWindows);
return 0;
}
}
}

View file

@ -0,0 +1,41 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Views.MouseUtilsPage"
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"
mc:Ignorable="d"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
AutomationProperties.LandmarkType="Main">
<controls:SettingsPageControl x:Uid="MouseUtils"
ModuleImageSource="ms-appx:///Assets/Modules/MouseUtils.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="MouseUtils_Enable_FindMyMouse" Icon="&#xF272;">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=TwoWay}" HorizontalAlignment="Right"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<CheckBox x:Uid="MouseUtils_Prevent_Activation_On_Game_Mode"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.FindMyMouseDoNotActivateOnGameMode}"
Margin="{StaticResource ExpanderSettingMargin}"
IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}" />
</controls:SettingExpander.Content>
</controls:SettingExpander>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_MouseUtils" Link="https://aka.ms/PowerToysOverview_MouseUtilities"/>
</controls:SettingsPageControl.PrimaryLinks>
<controls:SettingsPageControl.SecondaryLinks>
<controls:PageLink Text="Raymond Chen's Find My Mouse" Link="https://devblogs.microsoft.com/oldnewthing/author/oldnewthing"/>
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>

View file

@ -0,0 +1,23 @@
// 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.Library.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Views
{
public sealed partial class MouseUtilsPage : Page
{
private MouseUtilsViewModel ViewModel { get; set; }
public MouseUtilsPage()
{
var settingsUtils = new SettingsUtils();
ViewModel = new MouseUtilsViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<FindMyMouseSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
InitializeComponent();
}
}
}

View file

@ -0,0 +1,297 @@
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModels="using:Microsoft.PowerToys.Settings.UI.Library.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
xmlns:i="using:Microsoft.Xaml.Interactivity"
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Views.PowerLauncherPage"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
mc:Ignorable="d"
AutomationProperties.LandmarkType="Main">
<Page.Resources>
<converters:BoolToObjectConverter x:Key="BoolToVisibilityConverter" TrueValue="Visible" FalseValue="Collapsed"/>
<converters:BoolNegationConverter x:Key="BoolNegationConverter"/>
</Page.Resources>
<controls:SettingsPageControl x:Uid="PowerLauncher"
ModuleImageSource="ms-appx:///Assets/Modules/PowerLauncher.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<controls:Setting x:Uid="PowerLauncher_EnablePowerLauncher">
<controls:Setting.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsPowerToysRun.png" ShowAsMonochrome="False" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.EnablePowerLauncher, Mode=TwoWay}" />
</controls:Setting.ActionContent>
</controls:Setting>
<controls:SettingsGroup x:Uid="Shortcut" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="Activation_Shortcut" Icon="&#xEDA7;" Style="{StaticResource ExpanderHeaderSettingStyle}">
<controls:Setting.ActionContent>
<controls:ShortcutControl HotkeySettings="{x:Bind Path=ViewModel.OpenPowerLauncher, Mode=TwoWay}"
MinWidth="{StaticResource SettingActionControlMinWidth}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel>
<controls:CheckBoxWithDescriptionControl x:Uid="PowerLauncher_UseCentralizedKeyboardHook"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.UseCentralizedKeyboardHook}"
Margin="56, 0, 40, 16"/>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox x:Uid="PowerLauncher_IgnoreHotkeysInFullScreen"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.IgnoreHotkeysInFullScreen}"
Margin="{StaticResource ExpanderSettingMargin}" />
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
</controls:SettingsGroup>
<!--<Custom:HotkeySettingsControl x:Uid="PowerLauncher_OpenFileLocation"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
HotkeySettings="{Binding Path=ViewModel.OpenFileLocation, Mode=TwoWay}"
IsEnabled="False"
/>
<Custom:HotkeySettingsControl x:Uid="PowerLauncher_CopyPathLocation"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
HotkeySettings="{Binding Path=ViewModel.CopyPathLocation, Mode=TwoWay}"
Keys="Win, Ctrl, Alt, Shift"
IsEnabled="False"
/>
<Custom:HotkeySettingsControl x:Uid="PowerLauncher_OpenConsole"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
HotkeySettings="{Binding Path=ViewModel.OpenConsole, Mode=TwoWay}"
Keys="Win, Ctrl, Alt, Shift"
IsEnabled="False"
/>-->
<!--<CheckBox x:Uid="PowerLauncher_OverrideWinRKey"
Margin="{StaticResource SmallTopMargin}"
IsChecked="False"
IsEnabled="False"
/>-->
<!--<CheckBox x:Uid="PowerLauncher_OverrideWinSKey"
Margin="{StaticResource SmallTopMargin}"
IsChecked="{Binding Mode=TwoWay, Path=ViewModel.OverrideWinSKey}"
IsEnabled="False"
/>-->
<controls:SettingsGroup x:Uid="PowerLauncher_SearchResults" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="PowerLauncher_MaximumNumberOfResults" Icon="&#xE721;" Style="{StaticResource ExpanderHeaderSettingStyle}">
<controls:Setting.ActionContent>
<muxc:NumberBox Value="{Binding Mode=TwoWay, Path=MaximumNumberOfResults}"
MinWidth="{StaticResource SettingActionControlMinWidth}"
SpinButtonPlacementMode="Compact"
Minimum="1"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<CheckBox x:Uid="PowerLauncher_ClearInputOnLaunch" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.ClearInputOnLaunch}" Margin="{StaticResource ExpanderSettingMargin}" />
</controls:SettingExpander.Content>
</controls:SettingExpander>
</controls:SettingsGroup>
<!--<ComboBox x:Uid="PowerLauncher_SearchResultPreference"
MinWidth="320"
Margin="{StaticResource SmallTopMargin}"
ItemsSource="{Binding searchResultPreferencesOptions}"
SelectedItem="{Binding Mode=TwoWay, Path=SelectedSearchResultPreference}"
SelectedValuePath="Item2"
DisplayMemberPath="Item1"
IsEnabled="False"
/>
<ComboBox x:Uid="PowerLauncher_SearchTypePreference"
MinWidth="320"
Margin="{StaticResource SmallTopMargin}"
ItemsSource="{Binding searchTypePreferencesOptions}"
SelectedItem="{Binding Mode=TwoWay, Path=SelectedSearchTypePreference}"
SelectedValuePath="Item2"
DisplayMemberPath="Item1"
IsEnabled="False"
/>-->
<controls:SettingsGroup x:Uid="Run_PositionAppearance_GroupSettings" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}">
<controls:Setting x:Uid="Run_PositionHeader" Icon="&#xE18C;">
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.MonitorPositionIndex}" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="Run_Radio_Position_Cursor"/>
<ComboBoxItem x:Uid="Run_Radio_Position_Primary_Monitor"/>
<ComboBoxItem x:Uid="Run_Radio_Position_Focus"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="ColorModeHeader" Icon="&#xE790;">
<controls:Setting.Description>
<HyperlinkButton Click="OpenColorsSettings_Click"
x:Uid="Windows_Color_Settings"/>
</controls:Setting.Description>
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.ThemeIndex}" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="Radio_Theme_Dark"/>
<ComboBoxItem x:Uid="Radio_Theme_Light"/>
<ComboBoxItem x:Uid="Radio_Theme_Default"/>
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="PowerLauncher_Plugins" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher}">
<controls:Setting x:Uid="Run_PluginUseDescription" Icon="&#xEA86;">
<controls:Setting.ActionContent>
<AutoSuggestBox x:Uid="PowerLauncher_SearchList"
QueryIcon="Find"
MinWidth="{StaticResource SettingActionControlMinWidth}"
Text="{x:Bind ViewModel.SearchText, Mode=TwoWay}">
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="TextChanged">
<ic:InvokeCommandAction Command="{x:Bind ViewModel.SearchPluginsCommand}" />
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
</AutoSuggestBox>
</controls:Setting.ActionContent>
</controls:Setting>
<muxc:InfoBar x:Uid="Run_AllPluginsDisabled"
Severity="Error"
IsTabStop="{x:Bind ViewModel.ShowAllPluginsDisabledWarning, Mode=OneWay}"
IsOpen="{x:Bind ViewModel.ShowAllPluginsDisabledWarning, Mode=OneWay}"
IsClosable="False" />
<StackPanel Orientation="Horizontal" Visibility="{x:Bind ViewModel.ShowPluginsLoadingMessage, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
<muxc:ProgressRing IsActive="True" Width="20" Height="20" Margin="18,18" />
<TextBlock x:Uid="Run_PluginsLoading" Style="{ThemeResource SecondaryTextStyle}" VerticalAlignment="Center" />
</StackPanel>
<ListView ItemsSource="{x:Bind Path=ViewModel.Plugins, Mode=OneWay}"
IsItemClickEnabled="False"
SelectionMode="None"
x:Name="PluginsListView">
<ListView.ItemTemplate>
<DataTemplate x:DataType="ViewModels:PowerLauncherPluginViewModel" x:DefaultBindMode="OneWay">
<Grid>
<controls:SettingExpander>
<controls:SettingExpander.Header>
<controls:Setting Header="{x:Bind Path=Name}" Description="{x:Bind Description}" Style="{StaticResource ExpanderHeaderSettingStyle}">
<controls:Setting.Icon>
<Image Source="{x:Bind IconPath}"
Width="20"
Height="20" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<StackPanel Orientation="Horizontal" Spacing="16">
<!-- TODO(stefan)
<muxc:InfoBadge AutomationProperties.AccessibilityView="Raw"
Visibility="{x:Bind ShowNotAccessibleWarning}"
Style="{StaticResource CriticalIconInfoBadgeStyle}" />-->
<ToggleSwitch x:Uid="PowerLauncher_EnablePluginToggle"
IsOn="{x:Bind Path=Disabled, Converter={StaticResource BoolNegationConverter}, Mode=TwoWay}"/>
</StackPanel>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel>
<controls:Setting x:Uid="PowerLauncher_ActionKeyword" Style="{StaticResource ExpanderContentSettingStyle}" IsEnabled="{x:Bind Enabled, Mode=OneWay}">
<controls:Setting.ActionContent>
<TextBox Text="{x:Bind Path=ActionKeyword, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
MinWidth="{StaticResource SettingActionControlMinWidth}" />
</controls:Setting.ActionContent>
</controls:Setting>
<muxc:InfoBar Severity="Error" x:Uid="Run_NotAccessibleWarning"
IsTabStop="True"
IsOpen="{x:Bind ShowNotAccessibleWarning}"
IsClosable="False" />
<muxc:InfoBar Severity="Error"
x:Uid="Run_NotAllowedActionKeyword"
IsTabStop="True"
IsOpen="{x:Bind ShowNotAllowedKeywordWarning}"
IsClosable="False" />
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox
AutomationProperties.Name="{Binding ElementName=IncludeInGlobalResultTitle, Path=Text}"
IsChecked="{x:Bind Path=IsGlobal, Mode=TwoWay}"
IsEnabled="{x:Bind Enabled, Mode=OneWay}"
Margin="56, 0, 40, 16">
<StackPanel Orientation="Vertical">
<TextBlock x:Name="IncludeInGlobalResultTitle"
Margin="0,10,0,0"
x:Uid="PowerLauncher_IncludeInGlobalResultTitle" />
<controls:IsEnabledTextBlock x:Uid="PowerLauncher_IncludeInGlobalResultDescription"
FontSize="{StaticResource SecondaryTextFontSize}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"/>
</StackPanel>
</CheckBox>
<ListView ItemsSource="{x:Bind Path=AdditionalOptions}"
SelectionMode="None"
IsEnabled="{x:Bind Enabled, Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="ViewModels:PluginAdditionalOptionViewModel">
<StackPanel Orientation="Vertical">
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<CheckBox Content="{x:Bind Path=DisplayLabel}"
IsChecked="{x:Bind Path=Value, Mode=TwoWay}"
Margin="{StaticResource ExpanderSettingMargin}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Rectangle Style="{StaticResource ExpanderSeparatorStyle}" />
<TextBlock Opacity="{x:Bind DisabledOpacity}"
HorizontalAlignment="Right"
Style="{ThemeResource SecondaryTextStyle}"
Margin="{StaticResource ExpanderSettingMargin}">
<Run x:Uid="PowerLauncher_AuthoredBy" />
<Run FontWeight="SemiBold" Text="{x:Bind Author}" />
</TextBlock>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_Run" Link="https://aka.ms/PowerToysOverview_PowerToysRun"/>
</controls:SettingsPageControl.PrimaryLinks>
<controls:SettingsPageControl.SecondaryLinks>
<controls:PageLink Text="Wox" Link="https://github.com/Wox-launcher/Wox/"/>
<controls:PageLink Text="Beta Tadele's Window Walker" Link="https://github.com/betsegaw/windowwalker/"/>
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>

View file

@ -0,0 +1,108 @@
// 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.IO;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
using Microsoft.UI.Xaml.Controls;
// TODO(stefan)
using WindowsUI = Windows.UI;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Views
{
public sealed partial class PowerLauncherPage : Page
{
public PowerLauncherViewModel ViewModel { get; set; }
private readonly ObservableCollection<Tuple<string, string>> searchResultPreferencesOptions;
private readonly ObservableCollection<Tuple<string, string>> searchTypePreferencesOptions;
public PowerLauncherPage()
{
InitializeComponent();
var settingsUtils = new SettingsUtils();
PowerLauncherSettings settings = settingsUtils.GetSettingsOrDefault<PowerLauncherSettings>(PowerLauncherSettings.ModuleName);
ViewModel = new PowerLauncherViewModel(settings, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsDarkTheme);
DataContext = ViewModel;
_ = Helper.GetFileWatcher(PowerLauncherSettings.ModuleName, "settings.json", () =>
{
PowerLauncherSettings powerLauncherSettings = null;
try
{
powerLauncherSettings = settingsUtils.GetSettingsOrDefault<PowerLauncherSettings>(PowerLauncherSettings.ModuleName);
}
catch (IOException ex)
{
Logger.LogInfo(ex.Message);
}
if (powerLauncherSettings != null && !ViewModel.IsUpToDate(powerLauncherSettings))
{
_ = Dispatcher.RunAsync(WindowsUI.Core.CoreDispatcherPriority.Normal, () =>
{
DataContext = ViewModel = new PowerLauncherViewModel(powerLauncherSettings, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsDarkTheme);
// TODO(stefan)
// this.Bindings.Update();
});
}
});
// TODO(stefan)
/* var loader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
searchResultPreferencesOptions = new ObservableCollection<Tuple<string, string>>();
searchResultPreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchResultPreference_AlphabeticalOrder"), "alphabetical_order"));
searchResultPreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchResultPreference_MostRecentlyUsed"), "most_recently_used"));
searchResultPreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchResultPreference_RunningProcessesOpenApplications"), "running_processes_open_applications"));
searchTypePreferencesOptions = new ObservableCollection<Tuple<string, string>>();
searchTypePreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchTypePreference_ApplicationName"), "application_name"));
searchTypePreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchTypePreference_StringInApplication"), "string_in_application"));
searchTypePreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchTypePreference_ExecutableName"), "executable_name"));
*/ }
private void OpenColorsSettings_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
Helpers.StartProcessHelper.Start(Helpers.StartProcessHelper.ColorsSettings);
}
/*
public Tuple<string, string> SelectedSearchResultPreference
{
get
{
return searchResultPreferencesOptions.First(item => item.Item2 == ViewModel.SearchResultPreference);
}
set
{
if (ViewModel.SearchResultPreference != value.Item2)
{
ViewModel.SearchResultPreference = value.Item2;
}
}
}
public Tuple<string, string> SelectedSearchTypePreference
{
get
{
return searchTypePreferencesOptions.First(item => item.Item2 == ViewModel.SearchTypePreference);
}
set
{
if (ViewModel.SearchTypePreference != value.Item2)
{
ViewModel.SearchTypePreference = value.Item2;
}
}
}
*/
}
}

View file

@ -0,0 +1,89 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Views.PowerPreviewPage"
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"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d"
AutomationProperties.LandmarkType="Main">
<Page.Resources>
<converters:BoolToObjectConverter x:Key="BoolToVisibilityConverter" TrueValue="Collapsed" FalseValue="Visible"/>
</Page.Resources>
<controls:SettingsPageControl x:Uid="FileExplorerPreview"
ModuleImageSource="ms-appx:///Assets/Modules/PowerPreview.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical">
<muxc:InfoBar Severity="Warning"
x:Uid="FileExplorerPreview_RunAsAdminRequired"
IsOpen="True"
IsTabStop="True"
IsClosable="False"
Visibility="{Binding Mode=OneWay, Path=IsElevated, Converter={StaticResource BoolToVisibilityConverter}}" />
<muxc:InfoBar Severity="Informational"
x:Uid="FileExplorerPreview_AffectsAllUsers"
IsOpen="True"
IsTabStop="True"
IsClosable="False"
/>
<controls:SettingsGroup x:Uid="FileExplorerPreview_PreviewPane_GroupSettings">
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_Preview_SVG" Icon="&#xE91B;">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.SVGRenderIsEnabled}"
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_Preview_MD" Icon="&#xE943;">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.MDRenderIsEnabled}"
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_Preview_PDF" Icon="&#xEA90;">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.PDFRenderIsEnabled}"
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="FileExplorerPreview_IconThumbnail_GroupSettings">
<muxc:InfoBar Severity="Informational"
x:Uid="FileExplorerPreview_RebootRequired"
IsOpen="True"
IsTabStop="True"
IsClosable="False"
/>
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_SVG_Thumbnail" Icon="&#xE91B;">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.SVGThumbnailIsEnabled}"
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"/>
</controls:Setting.ActionContent>
</controls:Setting>
<controls:Setting x:Uid="FileExplorerPreview_ToggleSwitch_PDF_Thumbnail" Icon="&#xEA90;">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.PDFThumbnailIsEnabled}"
IsEnabled="{Binding Mode=OneWay, Path=IsElevated}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_PowerPreview" Link="https://aka.ms/PowerToysOverview_FileExplorerAddOns"/>
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
</Page>

View file

@ -0,0 +1,26 @@
// 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.Library.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class PowerPreviewPage : Page
{
public PowerPreviewViewModel ViewModel { get; set; }
public PowerPreviewPage()
{
InitializeComponent();
var settingsUtils = new SettingsUtils();
ViewModel = new PowerPreviewViewModel(SettingsRepository<PowerPreviewSettings>.GetInstance(settingsUtils), SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
}
}

View file

@ -0,0 +1,106 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.WinUI3.Views.PowerRenamePage"
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"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.WinUI3.Controls"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
mc:Ignorable="d"
AutomationProperties.LandmarkType="Main">
<Page.Resources>
<converters:BoolToObjectConverter x:Key="BoolToComboBoxIndexConverter" TrueValue="1" FalseValue="0"/>
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
</Page.Resources>
<controls:SettingsPageControl x:Uid="PowerRename"
ModuleImageSource="ms-appx:///Assets/Modules/PowerRename.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical"
x:Name="PowerRenameView"
HorizontalAlignment="Stretch">
<controls:Setting x:Uid="PowerRename_Toggle_Enable">
<controls:Setting.Icon>
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsPowerRename.png" ShowAsMonochrome="False" />
</controls:Setting.Icon>
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.IsEnabled}" />
</controls:Setting.ActionContent>
</controls:Setting>
<controls:SettingsGroup x:Uid="PowerRename_ShellIntegration" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="PowerRename_Toggle_ContextMenu" Style="{StaticResource ExpanderHeaderSettingStyle}">
<controls:Setting.ActionContent>
<ComboBox SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.EnabledOnContextExtendedMenu, Converter={StaticResource BoolToComboBoxIndexConverter}}" MinWidth="{StaticResource SettingActionControlMinWidth}">
<ComboBoxItem x:Uid="PowerRename_Toggle_StandardContextMenu" />
<ComboBoxItem x:Uid="PowerRename_Toggle_ExtendedContextMenu" />
</ComboBox>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel HorizontalAlignment="Stretch">
<CheckBox x:Uid="PowerRename_Toggle_HideIcon"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.EnabledOnContextMenu, Converter={StaticResource BoolNegationConverter}}"
Margin="{StaticResource ExpanderSettingMargin}"/>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="PowerRename_AutoCompleteHeader" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:SettingExpander IsExpanded="True">
<controls:SettingExpander.Header>
<controls:Setting x:Uid="PowerRename_Toggle_AutoComplete" Style="{StaticResource ExpanderHeaderSettingStyle}">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.MRUEnabled}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingExpander.Header>
<controls:SettingExpander.Content>
<StackPanel HorizontalAlignment="Stretch">
<controls:Setting x:Uid="PowerRename_Toggle_MaxDispListNum"
Style="{StaticResource ExpanderContentSettingStyle}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.GlobalAndMruEnabled}">
<controls:Setting.ActionContent>
<muxc:NumberBox SpinButtonPlacementMode="Compact"
HorizontalAlignment="Left"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.MaxDispListNum}"
Minimum="0"
Maximum="20"
MinWidth="{StaticResource SettingActionControlMinWidth}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</StackPanel>
</controls:SettingExpander.Content>
</controls:SettingExpander>
<controls:Setting x:Uid="PowerRename_Toggle_RestoreFlagsOnLaunch">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.RestoreFlagsOnLaunch}"/>
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="PowerRename_BehaviorHeader" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:Setting x:Uid="PowerRename_Toggle_UseBoostLib">
<controls:Setting.ActionContent>
<ToggleSwitch IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.UseBoostLib}" />
</controls:Setting.ActionContent>
</controls:Setting>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_PowerRename" Link="https://aka.ms/PowerToysOverview_PowerRename"/>
</controls:SettingsPageControl.PrimaryLinks>
<controls:SettingsPageControl.SecondaryLinks>
<controls:PageLink Text="Chris Davis's SmartRenamer" Link="https://github.com/chrdavis/SmartRename"/>
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>

View file

@ -0,0 +1,24 @@
// 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.Library.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.WinUI3.Views
{
public sealed partial class PowerRenamePage : Page
{
private PowerRenameViewModel ViewModel { get; set; }
public PowerRenamePage()
{
InitializeComponent();
var settingsUtils = new SettingsUtils();
ViewModel = new PowerRenameViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
}
}

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