mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 18:57:19 +02:00
[Feature] PowerToys hotkey conflict detection (#41029)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Implements comprehensive hotkey conflict detection and resolution system for PowerToys, providing real-time conflict checking and centralized management interface. ## PR Checklist - [ ] **Closes:** #xxx - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [x] **Localization:** All end-user-facing strings can be localized - [x] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [x] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: [Shortcut conflict detction dev spec](https://github.com/MicrosoftDocs/windows-dev-docs/pull/5519) ## TODO Lists - [x] Add real-time hotkey validation functionality to the hotkey dialog - [x] Immediately detect conflicts and update shortcut conflict status after applying new shortcuts - [x] Return conflict list from runner hotkey conflict detector for conflict checking. - [x] Implement the Tooltip for every shortcut control - [x] Add dialog UI for showing all the shortcut conflicts - [x] Support changing shortcut directly inside the shortcut conflict window/dialog, no need to nav to the settings page. - [x] Redesign the `ShortcutConflictDialogContentControl` to align with the spec - [x] Add navigating and changing hotkey auctionability to the `ShortcutConflictDialogContentControl` - [x] Add telemetry. Impemented in [another PR](https://github.com/shuaiyuanxx/PowerToys/pull/47) ## Shortcut Conflict Support Modules  <details> <summary>Demo videos</summary> https://github.com/user-attachments/assets/476d992c-c6ca-4bcd-a3f2-b26cc612d1b9 https://github.com/user-attachments/assets/1c1a2537-de54-4db2-bdbf-6f1908ff1ce7 https://github.com/user-attachments/assets/9c992254-fc2b-402c-beec-20fceef25e6b https://github.com/user-attachments/assets/d66abc1c-b8bf-45f8-a552-ec989dab310f </details> <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Manually validation performed. --------- Signed-off-by: Shawn Yuan <shuaiyuan@microsoft.com> Signed-off-by: Shuai Yuan <shuai.yuan.zju@gmail.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
x:Name="LayoutRoot"
|
||||
@@ -39,6 +40,7 @@
|
||||
Content="{Binding}"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}"
|
||||
FontWeight="SemiBold"
|
||||
IsInvalid="{Binding ElementName=LayoutRoot, Path=HasConflict}"
|
||||
IsTabStop="False"
|
||||
Style="{StaticResource AccentKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
|
||||
@@ -3,9 +3,15 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.WinUI;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts;
|
||||
using Microsoft.PowerToys.Settings.UI.Services;
|
||||
using Microsoft.PowerToys.Settings.UI.Views;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Automation;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
@@ -33,8 +39,9 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
|
||||
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);
|
||||
|
||||
public static readonly DependencyProperty AllowDisableProperty = DependencyProperty.Register("AllowDisable", typeof(bool), typeof(ShortcutControl), new PropertyMetadata(false, OnAllowDisableChanged));
|
||||
public static readonly DependencyProperty HasConflictProperty = DependencyProperty.Register("HasConflict", typeof(bool), typeof(ShortcutControl), new PropertyMetadata(false, OnHasConflictChanged));
|
||||
public static readonly DependencyProperty TooltipProperty = DependencyProperty.Register("Tooltip", typeof(string), typeof(ShortcutControl), new PropertyMetadata(null, OnTooltipChanged));
|
||||
|
||||
private static ResourceLoader resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
|
||||
|
||||
@@ -58,6 +65,28 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
description.Text = text;
|
||||
}
|
||||
|
||||
private static void OnHasConflictChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var control = d as ShortcutControl;
|
||||
if (control == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
control.UpdateKeyVisualStyles();
|
||||
}
|
||||
|
||||
private static void OnTooltipChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var control = d as ShortcutControl;
|
||||
if (control == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
control.UpdateTooltip();
|
||||
}
|
||||
|
||||
private ShortcutDialogContentControl c = new ShortcutDialogContentControl();
|
||||
private ContentDialog shortcutDialog;
|
||||
|
||||
@@ -67,6 +96,18 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
set => SetValue(AllowDisableProperty, value);
|
||||
}
|
||||
|
||||
public bool HasConflict
|
||||
{
|
||||
get => (bool)GetValue(HasConflictProperty);
|
||||
set => SetValue(HasConflictProperty, value);
|
||||
}
|
||||
|
||||
public string Tooltip
|
||||
{
|
||||
get => (string)GetValue(TooltipProperty);
|
||||
set => SetValue(TooltipProperty, value);
|
||||
}
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get
|
||||
@@ -101,14 +142,54 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
if (hotkeySettings != value)
|
||||
{
|
||||
// Unsubscribe from old settings
|
||||
if (hotkeySettings != null)
|
||||
{
|
||||
hotkeySettings.PropertyChanged -= OnHotkeySettingsPropertyChanged;
|
||||
}
|
||||
|
||||
hotkeySettings = value;
|
||||
SetValue(HotkeySettingsProperty, value);
|
||||
|
||||
// Subscribe to new settings
|
||||
if (hotkeySettings != null)
|
||||
{
|
||||
hotkeySettings.PropertyChanged += OnHotkeySettingsPropertyChanged;
|
||||
|
||||
// Update UI based on conflict properties
|
||||
UpdateConflictStatusFromHotkeySettings();
|
||||
}
|
||||
|
||||
SetKeys();
|
||||
c.Keys = HotkeySettings.GetKeysList();
|
||||
c.Keys = HotkeySettings?.GetKeysList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHotkeySettingsPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(HotkeySettings.HasConflict) ||
|
||||
e.PropertyName == nameof(HotkeySettings.ConflictDescription))
|
||||
{
|
||||
UpdateConflictStatusFromHotkeySettings();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateConflictStatusFromHotkeySettings()
|
||||
{
|
||||
if (hotkeySettings != null)
|
||||
{
|
||||
// Update the ShortcutControl's conflict properties from HotkeySettings
|
||||
HasConflict = hotkeySettings.HasConflict;
|
||||
Tooltip = hotkeySettings.HasConflict ? hotkeySettings.ConflictDescription : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
HasConflict = false;
|
||||
Tooltip = null;
|
||||
}
|
||||
}
|
||||
|
||||
public ShortcutControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -136,6 +217,29 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
OnAllowDisableChanged(this, null);
|
||||
}
|
||||
|
||||
private void UpdateKeyVisualStyles()
|
||||
{
|
||||
if (PreviewKeysControl?.ItemsSource != null)
|
||||
{
|
||||
// Force refresh of the ItemsControl to update KeyVisual styles
|
||||
var items = PreviewKeysControl.ItemsSource;
|
||||
PreviewKeysControl.ItemsSource = null;
|
||||
PreviewKeysControl.ItemsSource = items;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTooltip()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Tooltip))
|
||||
{
|
||||
ToolTipService.SetToolTip(EditButton, Tooltip);
|
||||
}
|
||||
else
|
||||
{
|
||||
ToolTipService.SetToolTip(EditButton, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void ShortcutControl_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
shortcutDialog.PrimaryButtonClick -= ShortcutDialog_PrimaryButtonClick;
|
||||
@@ -147,6 +251,12 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
App.GetSettingsWindow().Activated -= ShortcutDialog_SettingsWindow_Activated;
|
||||
}
|
||||
|
||||
// Unsubscribe from HotkeySettings property changes
|
||||
if (hotkeySettings != null)
|
||||
{
|
||||
hotkeySettings.PropertyChanged -= OnHotkeySettingsPropertyChanged;
|
||||
}
|
||||
|
||||
// Dispose the HotkeySettingsControlHook object to terminate the hook threads when the textbox is unloaded
|
||||
hook?.Dispose();
|
||||
|
||||
@@ -168,6 +278,9 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
App.GetSettingsWindow().Activated += ShortcutDialog_SettingsWindow_Activated;
|
||||
}
|
||||
|
||||
// Initialize tooltip when loaded
|
||||
UpdateTooltip();
|
||||
}
|
||||
|
||||
private void KeyEventHandler(int key, bool matchValue, int matchValueCode)
|
||||
@@ -302,6 +415,8 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
KeyEventHandler(key, true, key);
|
||||
|
||||
c.Keys = internalSettings.GetKeysList();
|
||||
c.ConflictMessage = string.Empty;
|
||||
c.HasConflict = false;
|
||||
|
||||
if (internalSettings.GetKeysList().Count == 0)
|
||||
{
|
||||
@@ -336,12 +451,74 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
else
|
||||
{
|
||||
EnableKeys();
|
||||
if (lastValidSettings.IsValid())
|
||||
{
|
||||
if (string.Equals(lastValidSettings.ToString(), hotkeySettings.ToString(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
c.HasConflict = hotkeySettings.HasConflict;
|
||||
c.ConflictMessage = hotkeySettings.ConflictDescription;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check for conflicts with the new hotkey settings
|
||||
CheckForConflicts(lastValidSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.IsWarningAltGr = internalSettings.Ctrl && internalSettings.Alt && !internalSettings.Win && (internalSettings.Code > 0);
|
||||
}
|
||||
|
||||
private void CheckForConflicts(HotkeySettings settings)
|
||||
{
|
||||
void UpdateUIForConflict(bool hasConflict, HotkeyConflictResponse hotkeyConflictResponse)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
if (hasConflict)
|
||||
{
|
||||
// Build conflict message from all conflicts - only show module names
|
||||
var conflictingModules = new HashSet<string>();
|
||||
|
||||
foreach (var conflict in hotkeyConflictResponse.AllConflicts)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(conflict.ModuleName))
|
||||
{
|
||||
conflictingModules.Add(conflict.ModuleName);
|
||||
}
|
||||
}
|
||||
|
||||
if (conflictingModules.Count > 0)
|
||||
{
|
||||
var moduleNames = conflictingModules.ToArray();
|
||||
var conflictMessage = moduleNames.Length == 1
|
||||
? $"Conflict detected with {moduleNames[0]}"
|
||||
: $"Conflicts detected with: {string.Join(", ", moduleNames)}";
|
||||
|
||||
c.ConflictMessage = conflictMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
c.ConflictMessage = "Conflict detected with unknown module";
|
||||
}
|
||||
|
||||
c.HasConflict = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
c.ConflictMessage = string.Empty;
|
||||
c.HasConflict = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
HotkeyConflictHelper.CheckHotkeyConflict(
|
||||
settings,
|
||||
ShellPage.SendDefaultIPCMessage,
|
||||
UpdateUIForConflict);
|
||||
}
|
||||
|
||||
private void EnableKeys()
|
||||
{
|
||||
shortcutDialog.IsPrimaryButtonEnabled = true;
|
||||
@@ -416,6 +593,9 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
c.Keys = null;
|
||||
c.Keys = HotkeySettings.GetKeysList();
|
||||
|
||||
c.HasConflict = hotkeySettings.HasConflict;
|
||||
c.ConflictMessage = hotkeySettings.ConflictDescription;
|
||||
|
||||
// 92 means the Win key. The logic is: warning should be visible if the shortcut contains Alt AND contains Ctrl AND NOT contains Win.
|
||||
// Additional key must be present, as this is a valid, previously used shortcut shown at dialog open. Check for presence of non-modifier-key is not necessary therefore
|
||||
c.IsWarningAltGr = c.Keys.Contains("Ctrl") && c.Keys.Contains("Alt") && !c.Keys.Contains(92);
|
||||
@@ -434,16 +614,32 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
|
||||
lastValidSettings = hotkeySettings;
|
||||
shortcutDialog.Hide();
|
||||
|
||||
// Send RequestAllConflicts IPC to update the UI after changed hotkey settings.
|
||||
GlobalHotkeyConflictManager.Instance?.RequestAllConflicts();
|
||||
}
|
||||
|
||||
private void ShortcutDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
if (ComboIsValid(lastValidSettings))
|
||||
{
|
||||
HotkeySettings = lastValidSettings with { };
|
||||
if (c.HasConflict)
|
||||
{
|
||||
lastValidSettings = lastValidSettings with { HasConflict = true };
|
||||
}
|
||||
else
|
||||
{
|
||||
lastValidSettings = lastValidSettings with { HasConflict = false };
|
||||
}
|
||||
|
||||
HotkeySettings = lastValidSettings;
|
||||
}
|
||||
|
||||
SetKeys();
|
||||
|
||||
// Send RequestAllConflicts IPC to update the UI after changed hotkey settings.
|
||||
GlobalHotkeyConflictManager.Instance?.RequestAllConflicts();
|
||||
|
||||
shortcutDialog.Hide();
|
||||
}
|
||||
|
||||
@@ -520,7 +716,7 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
|
||||
private void SetKeys()
|
||||
{
|
||||
var keys = HotkeySettings.GetKeysList();
|
||||
var keys = HotkeySettings?.GetKeysList();
|
||||
|
||||
if (keys != null && keys.Count > 0)
|
||||
{
|
||||
|
||||
@@ -63,6 +63,13 @@
|
||||
IsOpen="{Binding ElementName=ShortcutContentControl, Path=IsWarningAltGr, Mode=OneWay}"
|
||||
IsTabStop="{Binding ElementName=ShortcutContentControl, Path=IsWarningAltGr, Mode=OneWay}"
|
||||
Severity="Warning" />
|
||||
<InfoBar
|
||||
Title="Hotkey Conflict"
|
||||
IsClosable="False"
|
||||
IsOpen="{Binding ElementName=ShortcutContentControl, Path=HasConflict, Mode=OneWay}"
|
||||
IsTabStop="{Binding ElementName=ShortcutContentControl, Path=HasConflict, Mode=OneWay}"
|
||||
Message="{Binding ElementName=ShortcutContentControl, Path=ConflictMessage, Mode=OneWay}"
|
||||
Severity="Warning" />
|
||||
</Grid>
|
||||
<tk7controls:MarkdownTextBlock
|
||||
x:Uid="InvalidShortcutWarningLabel"
|
||||
@@ -71,4 +78,4 @@
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
@@ -11,6 +11,24 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
public sealed partial class ShortcutDialogContentControl : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty KeysProperty = DependencyProperty.Register("Keys", typeof(List<object>), typeof(ShortcutDialogContentControl), new PropertyMetadata(default(string)));
|
||||
public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register("IsError", typeof(bool), typeof(ShortcutDialogContentControl), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty IsWarningAltGrProperty = DependencyProperty.Register("IsWarningAltGr", typeof(bool), typeof(ShortcutDialogContentControl), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty HasConflictProperty = DependencyProperty.Register("HasConflict", typeof(bool), typeof(ShortcutDialogContentControl), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty ConflictMessageProperty = DependencyProperty.Register("ConflictMessage", typeof(string), typeof(ShortcutDialogContentControl), new PropertyMetadata(string.Empty));
|
||||
|
||||
public bool HasConflict
|
||||
{
|
||||
get => (bool)GetValue(HasConflictProperty);
|
||||
set => SetValue(HasConflictProperty, value);
|
||||
}
|
||||
|
||||
public string ConflictMessage
|
||||
{
|
||||
get => (string)GetValue(ConflictMessageProperty);
|
||||
set => SetValue(ConflictMessageProperty, value);
|
||||
}
|
||||
|
||||
public ShortcutDialogContentControl()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@@ -22,22 +40,16 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
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));
|
||||
|
||||
public bool IsWarningAltGr
|
||||
{
|
||||
get => (bool)GetValue(IsWarningAltGrProperty);
|
||||
set => SetValue(IsWarningAltGrProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsWarningAltGrProperty = DependencyProperty.Register("IsWarningAltGr", typeof(bool), typeof(ShortcutDialogContentControl), new PropertyMetadata(false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ItemsControl
|
||||
x:Name="ShortcutsControl"
|
||||
VerticalAlignment="Center"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
IsTabStop="False"
|
||||
@@ -32,14 +33,27 @@
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{Binding}"
|
||||
FontSize="12"
|
||||
IsTabStop="False" />
|
||||
IsTabStop="False"
|
||||
Style="{StaticResource DefaultKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<tk7controls:MarkdownTextBlock
|
||||
x:Name="LabelControl"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Background="Transparent"
|
||||
Text="{x:Bind Text}" />
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="LabelPlacementStates">
|
||||
<VisualState x:Name="LabelAfter" />
|
||||
<VisualState x:Name="LabelBefore">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="LabelControl.(Grid.Column)" Value="0" />
|
||||
<Setter Target="ShortcutsControl.(Grid.Column)" Value="1" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
set { SetValue(TextProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(ShortcutWithTextLabelControl), new PropertyMetadata(default(string)));
|
||||
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(nameof(Text), typeof(string), typeof(ShortcutWithTextLabelControl), new PropertyMetadata(default(string)));
|
||||
|
||||
public List<object> Keys
|
||||
{
|
||||
@@ -25,11 +25,40 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
set { SetValue(KeysProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty KeysProperty = DependencyProperty.Register("Keys", typeof(List<object>), typeof(ShortcutWithTextLabelControl), new PropertyMetadata(default(string)));
|
||||
public static readonly DependencyProperty KeysProperty = DependencyProperty.Register(nameof(Keys), typeof(List<object>), typeof(ShortcutWithTextLabelControl), new PropertyMetadata(default(string)));
|
||||
|
||||
public LabelPlacement LabelPlacement
|
||||
{
|
||||
get { return (LabelPlacement)GetValue(LabelPlacementProperty); }
|
||||
set { SetValue(LabelPlacementProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LabelPlacementProperty = DependencyProperty.Register(nameof(LabelPlacement), typeof(LabelPlacement), typeof(ShortcutWithTextLabelControl), new PropertyMetadata(defaultValue: LabelPlacement.After, OnIsLabelPlacementChanged));
|
||||
|
||||
public ShortcutWithTextLabelControl()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private static void OnIsLabelPlacementChanged(DependencyObject d, DependencyPropertyChangedEventArgs newValue)
|
||||
{
|
||||
if (d is ShortcutWithTextLabelControl labelControl)
|
||||
{
|
||||
if (labelControl.LabelPlacement == LabelPlacement.Before)
|
||||
{
|
||||
VisualStateManager.GoToState(labelControl, "LabelBefore", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
VisualStateManager.GoToState(labelControl, "LabelAfter", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum LabelPlacement
|
||||
{
|
||||
Before,
|
||||
After,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user