mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-23 19:49:43 +01:00
KBM improvements (#45697)
- Uses `Common.UI.Controls` for `KeyVisual` and `KeyCharPresenter`, deleted custom controls - Added input validation before clicking the save button. - Added an empty state when there are no remappings - Minor XAML fixes and improvements
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:Microsoft.PowerToys.Common.UI.Controls">
|
||||
xmlns:commoncontrols="using:Microsoft.PowerToys.Common.UI.Controls">
|
||||
|
||||
<Style BasedOn="{StaticResource DefaultKeyVisualStyle}" TargetType="local:KeyVisual" />
|
||||
<Style BasedOn="{StaticResource DefaultKeyVisualStyle}" TargetType="commoncontrols:KeyVisual" />
|
||||
|
||||
<Style x:Key="DefaultKeyVisualStyle" TargetType="local:KeyVisual">
|
||||
<Style x:Key="DefaultKeyVisualStyle" TargetType="commoncontrols:KeyVisual">
|
||||
<Setter Property="MinWidth" Value="16" />
|
||||
<Setter Property="AutomationProperties.AccessibilityView" Value="Raw" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
@@ -25,7 +25,7 @@
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyVisual">
|
||||
<ControlTemplate TargetType="commoncontrols:KeyVisual">
|
||||
<Grid
|
||||
x:Name="KeyHolder"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
@@ -40,7 +40,7 @@
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</Grid.BackgroundTransition>
|
||||
<local:KeyCharPresenter
|
||||
<commoncontrols:KeyCharPresenter
|
||||
x:Name="KeyPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
@@ -87,12 +87,12 @@
|
||||
<Style
|
||||
x:Key="SubtleKeyVisualStyle"
|
||||
BasedOn="{StaticResource DefaultKeyVisualStyle}"
|
||||
TargetType="local:KeyVisual">
|
||||
TargetType="commoncontrols:KeyVisual">
|
||||
<Setter Property="Background" Value="{ThemeResource SubtleFillColorTransparentBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SubtleFillColorTransparentBrush}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyVisual">
|
||||
<ControlTemplate TargetType="commoncontrols:KeyVisual">
|
||||
<Grid
|
||||
x:Name="KeyHolder"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
@@ -106,7 +106,7 @@
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</Grid.BackgroundTransition>
|
||||
<local:KeyCharPresenter
|
||||
<commoncontrols:KeyCharPresenter
|
||||
x:Name="KeyPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
@@ -145,14 +145,14 @@
|
||||
<Style
|
||||
x:Key="AccentKeyVisualStyle"
|
||||
BasedOn="{StaticResource DefaultKeyVisualStyle}"
|
||||
TargetType="local:KeyVisual">
|
||||
TargetType="commoncontrols:KeyVisual">
|
||||
<Setter Property="Background" Value="{ThemeResource AccentFillColorDefaultBrush}" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource TextOnAccentFillColorPrimaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource AccentControlElevationBorderBrush}" />
|
||||
<Setter Property="BackgroundSizing" Value="OuterBorderEdge" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyVisual">
|
||||
<ControlTemplate TargetType="commoncontrols:KeyVisual">
|
||||
<Grid
|
||||
x:Name="KeyHolder"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
@@ -168,7 +168,7 @@
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</Grid.BackgroundTransition>
|
||||
<local:KeyCharPresenter
|
||||
<commoncontrols:KeyCharPresenter
|
||||
x:Name="KeyPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:KeyboardManagerEditorUI.Controls"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI">
|
||||
|
||||
<Style BasedOn="{StaticResource DefaultKeyCharPresenterStyle}" TargetType="local:KeyCharPresenter" />
|
||||
|
||||
<Style x:Key="DefaultKeyCharPresenterStyle" TargetType="local:KeyCharPresenter">
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="AutomationProperties.AccessibilityView" Value="Raw" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid Height="{TemplateBinding FontSize}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Text="{TemplateBinding Content}"
|
||||
TextLineBounds="Tight" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="WindowsKeyCharPresenterStyle"
|
||||
BasedOn="{StaticResource DefaultKeyCharPresenterStyle}"
|
||||
TargetType="local:KeyCharPresenter">
|
||||
<!-- Scale to visually align the height of the Windows logo and text -->
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid Height="{TemplateBinding FontSize}">
|
||||
<Viewbox>
|
||||
<PathIcon Data="M9 20H0V11H9V20ZM20 20H11V11H20V20ZM9 9H0V0H9V9ZM20 9H11V0H20V9Z" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="OfficeKeyCharPresenterStyle"
|
||||
BasedOn="{StaticResource DefaultKeyCharPresenterStyle}"
|
||||
TargetType="local:KeyCharPresenter">
|
||||
<!-- Scale to visually align the height of the Office logo and text -->
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid Height="{TemplateBinding FontSize}">
|
||||
<Viewbox>
|
||||
<PathIcon Data="M1792 405v1238q0 33-10 62t-28 54-44 41-57 27l-555 159q-23 6-47 6-31 0-58-8t-53-24l-363-205q-20-11-31-29t-12-42q0-35 24-59t60-25h470V458L735 584q-43 15-69 53t-26 83v651q0 41-20 73t-55 53l-167 91q-23 12-46 12-40 0-68-28t-28-68V587q0-51 26-96t71-71L949 81q41-23 89-23 17 0 30 2t30 8l555 153q31 9 56 27t44 42 29 54 10 61zm-128 1238V405q0-22-13-38t-34-23l-273-75-64-18-64-18v1586l401-115q21-6 34-22t13-39z" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="CopilotKeyCharPresenterStyle"
|
||||
BasedOn="{StaticResource DefaultKeyCharPresenterStyle}"
|
||||
TargetType="local:KeyCharPresenter">
|
||||
<!-- Scale to visually align the height of the Copilot logo and text -->
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid Height="{TemplateBinding FontSize}">
|
||||
<Viewbox>
|
||||
<PathIcon Data="M0 1213q0-60 10-124t27-130 35-129 38-121q18-55 41-119t54-129 70-125 87-106 106-74 129-28h661q59 0 114 17t96 64q30 34 46 72t33 81l22 58q11 29 34 52 23 25 56 31t65 9h4q157 0 238 83t82 240q0 60-10 125t-27 130-35 128-38 121q-18 55-41 119t-54 129-70 125-87 106-106 74-129 28H790q-61 0-107-15t-82-44-61-72-46-98q-11-29-24-60t-35-55q-23-25-51-31t-60-9h-4q-157 0-238-83T0 1213zm598-957q-50 0-93 25t-79 68-67 94-54 108-42 106-31 91q-17 51-35 110t-33 119-26 121-10 114q0 102 43 149t147 47h163q39 0 74-12t64-35 50-53 34-67q19-58 35-115t35-117q35-117 70-232t72-233q23-73 47-147t63-141H598zm452 285q69-29 143-29h281q-18-29-29-59t-21-58-21-54-30-44-46-30-69-11q-32 0-60 9t-48 35q-17 23-31 53t-27 63-23 65-19 60zm-296 867h101q39 0 74-12t66-34 52-52 33-68l58-191 42-140q21-70 43-140 11-36 28-69t43-62h-101q-39 0-74 12t-66 34-52 52-33 68q-15 48-29 96t-29 96q-21 70-41 140t-44 140q-11 36-28 68t-43 62zm814-768q-39 0-74 12t-64 35-50 53-34 68q-56 174-107 347t-106 349q-23 74-47 147t-63 141h427q50 0 93-25t79-68 67-94 54-108 42-106 31-91q16-51 34-110t34-119 26-121 10-114q0-102-43-149t-147-47h-162zm-570 867q-69 29-143 29H564q17 28 29 58t22 58 24 54 32 45 48 30 71 11q31 0 60-8t49-35q15-19 29-50t28-65 24-69 18-58z" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="GlyphKeyCharPresenterStyle"
|
||||
BasedOn="{StaticResource DefaultKeyCharPresenterStyle}"
|
||||
TargetType="local:KeyCharPresenter">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid>
|
||||
<Viewbox>
|
||||
<FontIcon
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Glyph="{TemplateBinding Content}" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -1,32 +0,0 @@
|
||||
// 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.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Documents;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace KeyboardManagerEditorUI.Controls;
|
||||
|
||||
public sealed partial class KeyCharPresenter : Control
|
||||
{
|
||||
public KeyCharPresenter()
|
||||
{
|
||||
DefaultStyleKey = typeof(KeyCharPresenter);
|
||||
}
|
||||
|
||||
public object Content
|
||||
{
|
||||
get => (object)GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(object), typeof(KeyCharPresenter), new PropertyMetadata(default(string)));
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:KeyboardManagerEditorUI.Controls">
|
||||
|
||||
<Style BasedOn="{StaticResource DefaultKeyVisualStyle}" TargetType="local:KeyVisual" />
|
||||
|
||||
<Style x:Key="DefaultKeyVisualStyle" TargetType="local:KeyVisual">
|
||||
<Setter Property="MinWidth" Value="16" />
|
||||
<Setter Property="AutomationProperties.AccessibilityView" Value="Raw" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="MinHeight" Value="16" />
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorSecondaryBrush}" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource TextFillColorPrimaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
|
||||
<Setter Property="Padding" Value="4,4,4,4" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="CornerRadius" Value="2" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyVisual">
|
||||
<Grid
|
||||
x:Name="KeyHolder"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</Grid.BackgroundTransition>
|
||||
<local:KeyCharPresenter
|
||||
x:Name="KeyPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{TemplateBinding Content}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyHolder.Background" Value="{ThemeResource SubtleFillColorTransparentBrush}" />
|
||||
<Setter Target="KeyHolder.BorderBrush" Value="{ThemeResource CardStrokeColorDefaultSolidBrush}" />
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource ControlStrokeColorDefaultBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Invalid">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyHolder.Background" Value="{ThemeResource SystemFillColorCriticalBackgroundBrush}" />
|
||||
<Setter Target="KeyHolder.BorderBrush" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
<Setter Target="KeyHolder.BorderThickness" Value="1" />
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Warning">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyHolder.Background" Value="{ThemeResource SystemFillColorCautionBackgroundBrush}" />
|
||||
<Setter Target="KeyHolder.BorderBrush" Value="{ThemeResource SystemFillColorCautionBrush}" />
|
||||
<Setter Target="KeyHolder.BorderThickness" Value="1" />
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource SystemFillColorCautionBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="SubtleKeyVisualStyle"
|
||||
BasedOn="{StaticResource DefaultKeyVisualStyle}"
|
||||
TargetType="local:KeyVisual">
|
||||
<Setter Property="Background" Value="{ThemeResource SubtleFillColorTransparentBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SubtleFillColorTransparentBrush}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyVisual">
|
||||
<Grid
|
||||
x:Name="KeyHolder"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</Grid.BackgroundTransition>
|
||||
<local:KeyCharPresenter
|
||||
x:Name="KeyPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{TemplateBinding Content}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Invalid">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Warning">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource SystemFillColorCautionBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="AccentKeyVisualStyle"
|
||||
BasedOn="{StaticResource DefaultKeyVisualStyle}"
|
||||
TargetType="local:KeyVisual">
|
||||
<Setter Property="Background" Value="{ThemeResource AccentFillColorDefaultBrush}" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource TextOnAccentFillColorPrimaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource AccentControlElevationBorderBrush}" />
|
||||
<Setter Property="BackgroundSizing" Value="OuterBorderEdge" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyVisual">
|
||||
<Grid
|
||||
x:Name="KeyHolder"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</Grid.BackgroundTransition>
|
||||
<local:KeyCharPresenter
|
||||
x:Name="KeyPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyHolder.Background" Value="{ThemeResource AccentButtonBackgroundDisabled}" />
|
||||
<Setter Target="KeyHolder.BorderBrush" Value="{ThemeResource AccentButtonBorderBrushDisabled}" />
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource AccentButtonForegroundDisabled}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Invalid">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyHolder.Background" Value="{ThemeResource SystemFillColorCriticalBackgroundBrush}" />
|
||||
<Setter Target="KeyHolder.BorderBrush" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
<Setter Target="KeyHolder.BorderThickness" Value="1" />
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Warning">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyHolder.Background" Value="{ThemeResource SystemFillColorCautionBackgroundBrush}" />
|
||||
<Setter Target="KeyHolder.BorderBrush" Value="{ThemeResource SystemFillColorCautionBrush}" />
|
||||
<Setter Target="KeyHolder.BorderThickness" Value="1" />
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource SystemFillColorCautionBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -1,195 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Windows.System;
|
||||
|
||||
namespace KeyboardManagerEditorUI.Controls
|
||||
{
|
||||
[TemplatePart(Name = KeyPresenter, Type = typeof(KeyCharPresenter))]
|
||||
[TemplateVisualState(Name = NormalState, GroupName = "CommonStates")]
|
||||
[TemplateVisualState(Name = DisabledState, GroupName = "CommonStates")]
|
||||
[TemplateVisualState(Name = InvalidState, GroupName = "CommonStates")]
|
||||
[TemplateVisualState(Name = WarningState, GroupName = "CommonStates")]
|
||||
public sealed partial class KeyVisual : Control
|
||||
{
|
||||
private const string KeyPresenter = "KeyPresenter";
|
||||
private const string NormalState = "Normal";
|
||||
private const string DisabledState = "Disabled";
|
||||
private const string InvalidState = "Invalid";
|
||||
private const string WarningState = "Warning";
|
||||
private KeyCharPresenter _keyPresenter;
|
||||
|
||||
public object Content
|
||||
{
|
||||
get => (object)GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(object), typeof(KeyVisual), new PropertyMetadata(default(string), OnContentChanged));
|
||||
|
||||
public State State
|
||||
{
|
||||
get => (State)GetValue(StateProperty);
|
||||
set => SetValue(StateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty StateProperty = DependencyProperty.Register(nameof(State), typeof(State), typeof(KeyVisual), new PropertyMetadata(State.Normal, OnStateChanged));
|
||||
|
||||
public bool RenderKeyAsGlyph
|
||||
{
|
||||
get => (bool)GetValue(RenderKeyAsGlyphProperty);
|
||||
set => SetValue(RenderKeyAsGlyphProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty RenderKeyAsGlyphProperty = DependencyProperty.Register(nameof(RenderKeyAsGlyph), typeof(bool), typeof(KeyVisual), new PropertyMetadata(false, OnContentChanged));
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||
public KeyVisual()
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||
{
|
||||
this.DefaultStyleKey = typeof(KeyVisual);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
IsEnabledChanged -= KeyVisual_IsEnabledChanged;
|
||||
_keyPresenter = (KeyCharPresenter)this.GetTemplateChild(KeyPresenter);
|
||||
Update();
|
||||
SetVisualStates();
|
||||
IsEnabledChanged += KeyVisual_IsEnabledChanged;
|
||||
base.OnApplyTemplate();
|
||||
}
|
||||
|
||||
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((KeyVisual)d).SetVisualStates();
|
||||
}
|
||||
|
||||
private static void OnStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((KeyVisual)d).SetVisualStates();
|
||||
}
|
||||
|
||||
private void SetVisualStates()
|
||||
{
|
||||
if (this != null)
|
||||
{
|
||||
if (State == State.Error)
|
||||
{
|
||||
VisualStateManager.GoToState(this, InvalidState, true);
|
||||
}
|
||||
else if (State == State.Warning)
|
||||
{
|
||||
VisualStateManager.GoToState(this, WarningState, true);
|
||||
}
|
||||
else if (!IsEnabled)
|
||||
{
|
||||
VisualStateManager.GoToState(this, DisabledState, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
VisualStateManager.GoToState(this, NormalState, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Content == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Content is string key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case "Copilot":
|
||||
_keyPresenter.Style = (Style)Application.Current.Resources["CopilotKeyCharPresenterStyle"];
|
||||
break;
|
||||
|
||||
case "Office":
|
||||
_keyPresenter.Style = (Style)Application.Current.Resources["OfficeKeyCharPresenterStyle"];
|
||||
break;
|
||||
|
||||
default:
|
||||
_keyPresenter.Style = (Style)Application.Current.Resources["DefaultKeyCharPresenterStyle"];
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Content is int keyCode)
|
||||
{
|
||||
VirtualKey virtualKey = (VirtualKey)keyCode;
|
||||
switch (virtualKey)
|
||||
{
|
||||
case VirtualKey.Enter:
|
||||
SetGlyphOrText("\uE751", virtualKey);
|
||||
break;
|
||||
|
||||
case VirtualKey.Back:
|
||||
SetGlyphOrText("\uE750", virtualKey);
|
||||
break;
|
||||
|
||||
case VirtualKey.Shift:
|
||||
case (VirtualKey)160: // Left Shift
|
||||
case (VirtualKey)161: // Right Shift
|
||||
SetGlyphOrText("\uE752", virtualKey);
|
||||
break;
|
||||
|
||||
case VirtualKey.Up:
|
||||
_keyPresenter.Content = "\uE0E4";
|
||||
break;
|
||||
|
||||
case VirtualKey.Down:
|
||||
_keyPresenter.Content = "\uE0E5";
|
||||
break;
|
||||
|
||||
case VirtualKey.Left:
|
||||
_keyPresenter.Content = "\uE0E2";
|
||||
break;
|
||||
|
||||
case VirtualKey.Right:
|
||||
_keyPresenter.Content = "\uE0E3";
|
||||
break;
|
||||
|
||||
case VirtualKey.LeftWindows:
|
||||
case VirtualKey.RightWindows:
|
||||
_keyPresenter.Style = (Style)Application.Current.Resources["WindowsKeyCharPresenterStyle"];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetGlyphOrText(string glyph, VirtualKey key)
|
||||
{
|
||||
if (RenderKeyAsGlyph)
|
||||
{
|
||||
_keyPresenter.Content = glyph;
|
||||
_keyPresenter.Style = (Style)Application.Current.Resources["GlyphKeyCharPresenterStyle"];
|
||||
}
|
||||
else
|
||||
{
|
||||
_keyPresenter.Content = key.ToString();
|
||||
_keyPresenter.Style = (Style)Application.Current.Resources["DefaultKeyCharPresenterStyle"];
|
||||
}
|
||||
}
|
||||
|
||||
private void KeyVisual_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
SetVisualStates();
|
||||
}
|
||||
}
|
||||
|
||||
public enum State
|
||||
{
|
||||
Normal,
|
||||
Error,
|
||||
Warning,
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="KeyboardManagerEditorUI.Controls.UnifiedMappingControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:commoncontrols="using:Microsoft.PowerToys.Common.UI.Controls"
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:KeyboardManagerEditorUI.Controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
Loaded="UserControl_Loaded"
|
||||
mc:Ignorable="d">
|
||||
|
||||
@@ -95,7 +96,7 @@
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<local:KeyVisual
|
||||
<commoncontrols:KeyVisual
|
||||
Padding="8"
|
||||
Background="{ThemeResource ControlFillColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
@@ -260,7 +261,7 @@
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<local:KeyVisual
|
||||
<commoncontrols:KeyVisual
|
||||
Padding="8"
|
||||
Background="{ThemeResource CustomAccentBackgroundBrush}"
|
||||
BorderThickness="0"
|
||||
@@ -289,6 +290,7 @@
|
||||
GotFocus="TextContentBox_GotFocus"
|
||||
Header="Text to type"
|
||||
PlaceholderText="Enter the text to type when triggered"
|
||||
TextChanged="TextContentBox_TextChanged"
|
||||
TextWrapping="Wrap" />
|
||||
</tkcontrols:Case>
|
||||
|
||||
@@ -302,27 +304,37 @@
|
||||
FontSize="13"
|
||||
GotFocus="UrlPathInput_GotFocus"
|
||||
Header="URL to open"
|
||||
PlaceholderText="https://example.com" />
|
||||
PlaceholderText="https://example.com"
|
||||
TextChanged="UrlPathInput_TextChanged" />
|
||||
</tkcontrols:Case>
|
||||
|
||||
<!-- Open App Action -->
|
||||
<tkcontrols:Case Value="OpenApp">
|
||||
<StackPanel Orientation="Vertical" Spacing="16">
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox
|
||||
x:Name="ProgramPathInput"
|
||||
x:Uid="UnifiedMappingControlProgramPathTextBox"
|
||||
Width="240"
|
||||
HorizontalAlignment="Stretch"
|
||||
GotFocus="ProgramPathInput_GotFocus"
|
||||
Header="Program path"
|
||||
PlaceholderText="C:\Program Files\..." />
|
||||
PlaceholderText="C:\Program Files\..."
|
||||
TextChanged="ProgramPathInput_TextChanged" />
|
||||
<Button
|
||||
x:Name="ProgramPathSelectButton"
|
||||
x:Uid="UnifiedMappingControlPathSelectButton"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Bottom"
|
||||
AutomationProperties.Name="Select program path"
|
||||
Click="ProgramPathSelectButton_Click"
|
||||
Content="Browse..." />
|
||||
</StackPanel>
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=16}"
|
||||
Style="{StaticResource SubtleButtonStyle}" />
|
||||
</Grid>
|
||||
|
||||
<TextBox
|
||||
x:Name="ProgramArgsInput"
|
||||
@@ -331,21 +343,29 @@
|
||||
Header="Arguments (optional)"
|
||||
PlaceholderText="--arg1 value1" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<Grid ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox
|
||||
x:Name="StartInPathInput"
|
||||
x:Uid="UnifiedMappingControlStartInTextBox"
|
||||
Width="240"
|
||||
HorizontalAlignment="Stretch"
|
||||
GotFocus="StartInPathInput_GotFocus"
|
||||
Header="Start in directory (optional)"
|
||||
PlaceholderText="C:\Users\..." />
|
||||
<Button
|
||||
x:Name="StartInSelectButton"
|
||||
x:Uid="UnifiedMappingControlStartInSelectButton"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Bottom"
|
||||
AutomationProperties.Name="Select start directory"
|
||||
Click="StartInSelectButton_Click"
|
||||
Content="Browse..." />
|
||||
</StackPanel>
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=16}"
|
||||
Style="{StaticResource SubtleButtonStyle}" />
|
||||
</Grid>
|
||||
|
||||
<ComboBox
|
||||
x:Name="ElevationComboBox"
|
||||
@@ -353,9 +373,9 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
Header="Run as"
|
||||
SelectedIndex="0">
|
||||
<x:String>Normal</x:String>
|
||||
<x:String>Elevated</x:String>
|
||||
<x:String>Different user</x:String>
|
||||
<ComboBoxItem Content="Normal" />
|
||||
<ComboBoxItem Content="Elevated" />
|
||||
<ComboBoxItem Content="Different user" />
|
||||
</ComboBox>
|
||||
|
||||
<ComboBox
|
||||
@@ -364,11 +384,11 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
Header="If already running"
|
||||
SelectedIndex="0">
|
||||
<x:String>Show window</x:String>
|
||||
<x:String>Start another</x:String>
|
||||
<x:String>Do nothing</x:String>
|
||||
<x:String>Close</x:String>
|
||||
<x:String>End task</x:String>
|
||||
<ComboBoxItem Content="Show window" />
|
||||
<ComboBoxItem Content="Start another" />
|
||||
<ComboBoxItem Content="Do nothing" />
|
||||
<ComboBoxItem Content="Close" />
|
||||
<ComboBoxItem Content="End task" />
|
||||
</ComboBox>
|
||||
|
||||
<ComboBox
|
||||
@@ -377,10 +397,10 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
Header="Window visibility"
|
||||
SelectedIndex="0">
|
||||
<x:String>Normal</x:String>
|
||||
<x:String>Hidden</x:String>
|
||||
<x:String>Minimized</x:String>
|
||||
<x:String>Maximized</x:String>
|
||||
<ComboBoxItem Content="Normal" />
|
||||
<ComboBoxItem Content="Hidden" />
|
||||
<ComboBoxItem Content="Minimized" />
|
||||
<ComboBoxItem Content="Maximized" />
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
</tkcontrols:Case>
|
||||
@@ -401,7 +421,7 @@
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="0,16,0,0"
|
||||
IsClosable="True"
|
||||
IsClosable="False"
|
||||
IsOpen="False"
|
||||
Severity="Warning" />
|
||||
</Grid>
|
||||
|
||||
@@ -38,6 +38,20 @@ namespace KeyboardManagerEditorUI.Controls
|
||||
|
||||
private KeyInputMode _currentInputMode = KeyInputMode.OriginalKeys;
|
||||
|
||||
// Dirty tracking: marks fields that have had content then were cleared
|
||||
private bool _textContentDirty;
|
||||
private bool _urlPathDirty;
|
||||
private bool _programPathDirty;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
/// Raised whenever the validation state of the control changes (inputs filled/cleared).
|
||||
/// </summary>
|
||||
public event EventHandler? ValidationStateChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Enums
|
||||
@@ -132,6 +146,9 @@ namespace KeyboardManagerEditorUI.Controls
|
||||
TriggerKeys.ItemsSource = _triggerKeys;
|
||||
ActionKeys.ItemsSource = _actionKeys;
|
||||
|
||||
_triggerKeys.CollectionChanged += (_, _) => RaiseValidationStateChanged();
|
||||
_actionKeys.CollectionChanged += (_, _) => RaiseValidationStateChanged();
|
||||
|
||||
this.Unloaded += UnifiedMappingControl_Unloaded;
|
||||
}
|
||||
|
||||
@@ -226,6 +243,9 @@ namespace KeyboardManagerEditorUI.Controls
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HideValidationMessage();
|
||||
RaiseValidationStateChanged();
|
||||
}
|
||||
|
||||
private void ActionKeyToggleBtn_Checked(object sender, RoutedEventArgs e)
|
||||
@@ -309,18 +329,36 @@ namespace KeyboardManagerEditorUI.Controls
|
||||
UncheckAllToggleButtons();
|
||||
}
|
||||
|
||||
private void TextContentBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
_textContentDirty = true;
|
||||
RaiseValidationStateChanged();
|
||||
}
|
||||
|
||||
private void UrlPathInput_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CleanupKeyboardHook();
|
||||
UncheckAllToggleButtons();
|
||||
}
|
||||
|
||||
private void UrlPathInput_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
_urlPathDirty = true;
|
||||
RaiseValidationStateChanged();
|
||||
}
|
||||
|
||||
private void ProgramPathInput_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CleanupKeyboardHook();
|
||||
UncheckAllToggleButtons();
|
||||
}
|
||||
|
||||
private void ProgramPathInput_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
_programPathDirty = true;
|
||||
RaiseValidationStateChanged();
|
||||
}
|
||||
|
||||
private void ProgramArgsInput_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CleanupKeyboardHook();
|
||||
@@ -351,6 +389,7 @@ namespace KeyboardManagerEditorUI.Controls
|
||||
if (file != null)
|
||||
{
|
||||
ProgramPathInput.Text = file.Path;
|
||||
RaiseValidationStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,6 +545,31 @@ namespace KeyboardManagerEditorUI.Controls
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public API - Validation
|
||||
|
||||
/// <summary>
|
||||
/// Returns true when all required fields for the current action type are filled.
|
||||
/// </summary>
|
||||
public bool IsInputComplete()
|
||||
{
|
||||
// Trigger keys are always required
|
||||
if (_triggerKeys.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return CurrentActionType switch
|
||||
{
|
||||
ActionType.KeyOrShortcut => _actionKeys.Count > 0,
|
||||
ActionType.Text => !string.IsNullOrWhiteSpace(TextContentBox?.Text),
|
||||
ActionType.OpenUrl => !string.IsNullOrWhiteSpace(UrlPathInput?.Text),
|
||||
ActionType.OpenApp => !string.IsNullOrWhiteSpace(ProgramPathInput?.Text),
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public API - Setters
|
||||
|
||||
/// <summary>
|
||||
@@ -686,6 +750,52 @@ namespace KeyboardManagerEditorUI.Controls
|
||||
KeyboardHookHelper.Instance.CleanupHook();
|
||||
}
|
||||
|
||||
private void RaiseValidationStateChanged()
|
||||
{
|
||||
UpdateInlineValidation();
|
||||
ValidationStateChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows or hides the inline validation InfoBar based on the current state.
|
||||
/// Only shows errors for output fields that have been interacted with (had content then cleared).
|
||||
/// </summary>
|
||||
private void UpdateInlineValidation()
|
||||
{
|
||||
// Only validate the active action type's output field
|
||||
switch (CurrentActionType)
|
||||
{
|
||||
case ActionType.Text:
|
||||
if (TextContentBox != null && _textContentDirty && string.IsNullOrWhiteSpace(TextContentBox.Text))
|
||||
{
|
||||
ShowValidationErrorFromType(ValidationErrorType.EmptyTargetText);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ActionType.OpenUrl:
|
||||
if (UrlPathInput != null && _urlPathDirty && string.IsNullOrWhiteSpace(UrlPathInput.Text))
|
||||
{
|
||||
ShowValidationErrorFromType(ValidationErrorType.EmptyUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ActionType.OpenApp:
|
||||
if (ProgramPathInput != null && _programPathDirty && string.IsNullOrWhiteSpace(ProgramPathInput.Text))
|
||||
{
|
||||
ShowValidationErrorFromType(ValidationErrorType.EmptyProgramPath);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
HideValidationMessage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets all inputs to their default state.
|
||||
/// </summary>
|
||||
@@ -698,6 +808,11 @@ namespace KeyboardManagerEditorUI.Controls
|
||||
|
||||
_currentInputMode = KeyInputMode.OriginalKeys;
|
||||
|
||||
// Reset dirty tracking
|
||||
_textContentDirty = false;
|
||||
_urlPathDirty = false;
|
||||
_programPathDirty = false;
|
||||
|
||||
// Hide any validation messages
|
||||
HideValidationMessage();
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace KeyboardManagerEditorUI.Helpers
|
||||
DuplicateMapping,
|
||||
SelfMapping,
|
||||
EmptyTargetText,
|
||||
EmptyUrl,
|
||||
EmptyProgramPath,
|
||||
OneKeyMapping,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace KeyboardManagerEditorUI.Helpers
|
||||
{ ValidationErrorType.DuplicateMapping, ("Duplicate Remapping", "This key or shortcut is already remapped.") },
|
||||
{ ValidationErrorType.SelfMapping, ("Invalid Remapping", "A key or shortcut cannot be remapped to itself. Please choose a different target.") },
|
||||
{ ValidationErrorType.EmptyTargetText, ("Missing Target Text", "Please enter the text to be inserted when the shortcut is pressed.") },
|
||||
{ ValidationErrorType.EmptyUrl, ("Missing URL", "Please enter the URL to open when the shortcut is pressed.") },
|
||||
{ ValidationErrorType.EmptyProgramPath, ("Missing Program Path", "Please enter the program path to launch when the shortcut is pressed.") },
|
||||
{ ValidationErrorType.OneKeyMapping, ("Invalid Remapping", "A single key cannot be remapped to a Program or URL shortcut. Please choose a combination of keys.") },
|
||||
};
|
||||
|
||||
@@ -163,6 +165,40 @@ namespace KeyboardManagerEditorUI.Helpers
|
||||
return error;
|
||||
}
|
||||
|
||||
public static ValidationErrorType ValidateUrlMapping(
|
||||
List<string> originalKeys,
|
||||
string url,
|
||||
bool isAppSpecific,
|
||||
string appName,
|
||||
KeyboardMappingService mappingService,
|
||||
bool isEditMode = false,
|
||||
Remapping? editingRemapping = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
return ValidationErrorType.EmptyUrl;
|
||||
}
|
||||
|
||||
return ValidateProgramOrUrlMapping(originalKeys, isAppSpecific, appName, mappingService, isEditMode, editingRemapping);
|
||||
}
|
||||
|
||||
public static ValidationErrorType ValidateAppMapping(
|
||||
List<string> originalKeys,
|
||||
string programPath,
|
||||
bool isAppSpecific,
|
||||
string appName,
|
||||
KeyboardMappingService mappingService,
|
||||
bool isEditMode = false,
|
||||
Remapping? editingRemapping = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(programPath))
|
||||
{
|
||||
return ValidationErrorType.EmptyProgramPath;
|
||||
}
|
||||
|
||||
return ValidateProgramOrUrlMapping(originalKeys, isAppSpecific, appName, mappingService, isEditMode, editingRemapping);
|
||||
}
|
||||
|
||||
public static bool IsDuplicateMapping(List<string> keys, bool isEditMode, KeyboardMappingService mappingService)
|
||||
{
|
||||
int upperLimit = isEditMode ? 1 : 0;
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\Common.UI\Common.UI.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\Common.UI.Controls\Common.UI.Controls.csproj" />
|
||||
<ProjectReference Include="..\KeyboardManagerEditorLibraryWrapper\KeyboardManagerEditorLibraryWrapper.vcxproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -8,19 +8,15 @@
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<ResourceDictionary Source="/Controls/KeyVisual/KeyVisual.xaml" />
|
||||
<ResourceDictionary Source="/Controls/KeyVisual/KeyCharPresenter.xaml" />
|
||||
<ResourceDictionary Source="/Controls/IconLabel/IconLabelControl.xaml" />
|
||||
<ResourceDictionary Source="/Controls/IconLabelControl.xaml" />
|
||||
<ResourceDictionary Source="/Styles/Button.xaml" />
|
||||
<ResourceDictionary Source="/Styles/Colors.xaml" />
|
||||
<ResourceDictionary Source="ms-appx:///PowerToys.Common.UI.Controls/Controls/KeyVisual/KeyVisual.xaml" />
|
||||
<ResourceDictionary Source="ms-appx:///PowerToys.Common.UI.Controls/Controls/KeyVisual/KeyCharPresenter.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<!-- Other app resources here -->
|
||||
|
||||
<x:Double x:Key="ContentDialogMaxWidth">960</x:Double>
|
||||
|
||||
<!-- Icons -->
|
||||
<x:String x:Key="ArrowIconData">M12.001 2C17.5238 2 22.001 6.47715 22.001 12C22.001 17.5228 17.5238 22 12.001 22C6.47813 22 2.00098 17.5228 2.00098 12C2.00098 6.47715 6.47813 2 12.001 2ZM12.7813 7.46897L12.6972 7.39635C12.4362 7.2027 12.078 7.20031 11.8146 7.38918L11.7206 7.46897L11.648 7.55308C11.4544 7.81407 11.452 8.17229 11.6409 8.43568L11.7206 8.52963L14.4403 11.2493H7.75027L7.6485 11.2561C7.31571 11.3013 7.05227 11.5647 7.00712 11.8975L7.00027 11.9993L7.00712 12.1011C7.05227 12.4339 7.31571 12.6973 7.6485 12.7424L7.75027 12.7493H14.4403L11.72 15.4697L11.6474 15.5538C11.4295 15.8474 11.4536 16.264 11.7198 16.5303C11.9861 16.7967 12.4027 16.8209 12.6964 16.6032L12.7805 16.5306L16.782 12.5306L16.8547 12.4464C17.0484 12.1854 17.0508 11.8272 16.8619 11.5638L16.7821 11.4698L12.7813 7.46897L12.6972 7.39635L12.7813 7.46897Z</x:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</TitleBar.LeftHeader>
|
||||
</TitleBar>
|
||||
|
||||
<pages:All
|
||||
<pages:MainPage
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch" />
|
||||
|
||||
@@ -33,9 +33,6 @@ namespace KeyboardManagerEditorUI
|
||||
SetTitleBar();
|
||||
this.Activated += MainWindow_Activated;
|
||||
this.Closed += MainWindow_Closed;
|
||||
|
||||
// Set the default page
|
||||
// RootView.SelectedItem = RootView.MenuItems[0];
|
||||
}
|
||||
|
||||
private void SetTitleBar()
|
||||
|
||||
@@ -1,488 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Page
|
||||
x:Class="KeyboardManagerEditorUI.Pages.All"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:KeyboardManagerEditorUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:helper="using:KeyboardManagerEditorUI.Helpers"
|
||||
xmlns:local="using:KeyboardManagerEditorUI.Pages"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Page.Resources>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">800</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxHeight">800</x:Double>
|
||||
<Style
|
||||
x:Key="OriginalKeyVisualStyle"
|
||||
BasedOn="{StaticResource DefaultKeyVisualStyle}"
|
||||
TargetType="controls:KeyVisual">
|
||||
<Setter Property="Padding" Value="6" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Background" Value="{ThemeResource ControlFillColorDefaultBrush}" />
|
||||
<Setter Property="CornerRadius" Value="{StaticResource ControlCornerRadius}" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="RenderKeyAsGlyph" Value="True" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="RemappedKeyVisualStyle"
|
||||
BasedOn="{StaticResource OriginalKeyVisualStyle}"
|
||||
TargetType="controls:KeyVisual">
|
||||
<Setter Property="Background" Value="{ThemeResource CustomAccentBackgroundBrush}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource AccentTextFillColorPrimaryBrush}" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="RemappedIconLabelControlStyle"
|
||||
BasedOn="{StaticResource DefaultIconLabelControlStyle}"
|
||||
TargetType="controls:IconLabelControl">
|
||||
<Setter Property="Background" Value="{ThemeResource CustomAccentBackgroundBrush}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="6" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="CornerRadius" Value="{StaticResource ControlCornerRadius}" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource AccentTextFillColorPrimaryBrush}" />
|
||||
</Style>
|
||||
<Style x:Key="ItemDividerStyle" TargetType="Rectangle">
|
||||
<Style.Setters>
|
||||
<Setter Property="Grid.ColumnSpan" Value="2" />
|
||||
<Setter Property="Height" Value="1" />
|
||||
<Setter Property="Margin" Value="-16,0,-16,-8" />
|
||||
<Setter Property="Fill" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalAlignment" Value="Bottom" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
<tkconverters:DoubleToVisibilityConverter
|
||||
x:Key="CountToVisibilityConverter"
|
||||
FalseValue="Collapsed"
|
||||
GreaterThan="0"
|
||||
TrueValue="Visible" />
|
||||
<tkconverters:StringVisibilityConverter
|
||||
x:Key="StringVisibilityConverter"
|
||||
EmptyValue="Collapsed"
|
||||
NotEmptyValue="Visible" />
|
||||
</Page.Resources>
|
||||
|
||||
<Grid Padding="16" RowSpacing="16">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="64" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid>
|
||||
<Button x:Name="NewRemappingBtn" Click="NewRemappingBtn_Click">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<FontIcon
|
||||
FontSize="14"
|
||||
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
Glyph="" />
|
||||
<TextBlock VerticalAlignment="Center" Text="Add new remapping" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Background="{ThemeResource LayerFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{ThemeResource OverlayCornerRadius}">
|
||||
<ScrollViewer VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto">
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical" Spacing="24">
|
||||
<!-- Remappings Section -->
|
||||
<StackPanel Orientation="Vertical" Visibility="{x:Bind RemappingList.Count, Mode=OneWay, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
<TextBlock
|
||||
Margin="16,16,0,8"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Keys and shortcuts" />
|
||||
<Rectangle
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<ListView
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="RemappingsList_ItemClick"
|
||||
ItemsSource="{x:Bind RemappingList}"
|
||||
ScrollViewer.VerticalScrollMode="Disabled"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="helper:Remapping">
|
||||
<Grid MinHeight="48" Padding="0,8,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Rectangle Style="{StaticResource ItemDividerStyle}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ItemsControl VerticalAlignment="Center" ItemsSource="{x:Bind Shortcut}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:KeyVisual Content="{Binding}" Style="{StaticResource OriginalKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="maps to" />
|
||||
<ItemsControl VerticalAlignment="Center" ItemsSource="{x:Bind RemappedKeys}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:KeyVisual Content="{Binding}" Style="{StaticResource RemappedKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind AppName, Converter={StaticResource StringVisibilityConverter}}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="in" />
|
||||
<controls:IconLabelControl ActionType="Program" Label="{x:Bind AppName}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<ToggleSwitch
|
||||
IsOn="{x:Bind IsActive}"
|
||||
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}"
|
||||
Toggled="ToggleSwitch_Toggled" />
|
||||
<Button
|
||||
VerticalAlignment="Center"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
Click="DeleteMapping_Click"
|
||||
Icon="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Tag="{x:Bind}"
|
||||
Text="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Text Section -->
|
||||
<StackPanel Orientation="Vertical" Visibility="{x:Bind TextMappings.Count, Mode=OneWay, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
<TextBlock
|
||||
Margin="16,16,0,8"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Text" />
|
||||
<Rectangle
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<ListView
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="TextMappingsList_ItemClick"
|
||||
ItemsSource="{x:Bind TextMappings}"
|
||||
ScrollViewer.VerticalScrollMode="Disabled"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="helper:TextMapping">
|
||||
<Grid MinHeight="48" Padding="0,8,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Rectangle Style="{StaticResource ItemDividerStyle}" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ItemsControl VerticalAlignment="Center" ItemsSource="{x:Bind Shortcut}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:KeyVisual Content="{Binding}" Style="{StaticResource OriginalKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="inserts" />
|
||||
<controls:IconLabelControl
|
||||
ActionType="Text"
|
||||
Label="{x:Bind Text}"
|
||||
Style="{StaticResource RemappedIconLabelControlStyle}" />
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind AppName, Converter={StaticResource StringVisibilityConverter}}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="in" />
|
||||
<controls:IconLabelControl ActionType="Program" Label="{x:Bind AppName}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<ToggleSwitch
|
||||
IsOn="{x:Bind IsActive}"
|
||||
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}"
|
||||
Toggled="ToggleSwitch_Toggled" />
|
||||
<Button
|
||||
VerticalAlignment="Center"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
Click="DeleteMapping_Click"
|
||||
Icon="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Tag="{x:Bind}"
|
||||
Text="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Programs Section -->
|
||||
<StackPanel Orientation="Vertical" Visibility="{x:Bind ProgramShortcuts.Count, Mode=OneWay, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
<TextBlock
|
||||
Margin="16,16,0,8"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Programs" />
|
||||
<Rectangle
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
|
||||
<ListView
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="ProgramShortcutsList_ItemClick"
|
||||
ItemsSource="{x:Bind ProgramShortcuts}"
|
||||
ScrollViewer.VerticalScrollMode="Disabled"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="helper:ProgramShortcut">
|
||||
<Grid MinHeight="48" Padding="0,8,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Rectangle Style="{StaticResource ItemDividerStyle}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ItemsControl VerticalAlignment="Center" ItemsSource="{x:Bind Shortcut}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:KeyVisual Content="{Binding}" Style="{StaticResource OriginalKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="opens" />
|
||||
<controls:IconLabelControl
|
||||
ActionType="Program"
|
||||
Label="{x:Bind AppToRun}"
|
||||
Style="{StaticResource RemappedIconLabelControlStyle}" />
|
||||
<!-- TO DO: Add a ToolTip or Flyout with some of the important advanced info like args -->
|
||||
<!-- {x:Bind Args} -->
|
||||
<!--<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind AppName, Converter={StaticResource StringVisibilityConverter}}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="in" />
|
||||
<controls:IconLabelControl ActionType="Program" Label="{x:Bind AppName}" />
|
||||
</StackPanel>-->
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<ToggleSwitch
|
||||
IsOn="{x:Bind IsActive}"
|
||||
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}"
|
||||
Toggled="ToggleSwitch_Toggled" />
|
||||
<Button
|
||||
VerticalAlignment="Center"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
Click="DeleteMapping_Click"
|
||||
Icon="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Tag="{x:Bind}"
|
||||
Text="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
|
||||
<!-- URLs Section -->
|
||||
<StackPanel Orientation="Vertical" Visibility="{x:Bind UrlShortcuts.Count, Mode=OneWay, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
<TextBlock
|
||||
Margin="16,16,0,8"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Urls" />
|
||||
<Rectangle
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<ListView
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="UrlShortcutsList_ItemClick"
|
||||
ItemsSource="{x:Bind UrlShortcuts}"
|
||||
ScrollViewer.VerticalScrollMode="Disabled"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="helper:URLShortcut">
|
||||
<Grid MinHeight="48" Padding="0,8,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Rectangle Style="{StaticResource ItemDividerStyle}" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ItemsControl VerticalAlignment="Center" ItemsSource="{x:Bind Shortcut}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:KeyVisual Content="{Binding}" Style="{StaticResource OriginalKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="opens" />
|
||||
<controls:IconLabelControl
|
||||
ActionType="Url"
|
||||
Label="{x:Bind URL}"
|
||||
Style="{StaticResource RemappedIconLabelControlStyle}" />
|
||||
<!--<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind AppName, Converter={StaticResource StringVisibilityConverter}}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="in" />
|
||||
<controls:IconLabelControl ActionType="Program" Label="{x:Bind AppName}" />
|
||||
</StackPanel>-->
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<ToggleSwitch
|
||||
IsOn="{x:Bind IsActive}"
|
||||
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}"
|
||||
Toggled="ToggleSwitch_Toggled" />
|
||||
<Button
|
||||
VerticalAlignment="Center"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
Click="DeleteMapping_Click"
|
||||
Icon="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Tag="{x:Bind}"
|
||||
Text="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
<!-- Content Dialog for new remapping -->
|
||||
<ContentDialog
|
||||
x:Name="RemappingDialog"
|
||||
Title="Add new remapping"
|
||||
Width="760"
|
||||
MinWidth="800"
|
||||
MinHeight="500"
|
||||
MaxWidth="900"
|
||||
CloseButtonText="Cancel"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonStyle="{StaticResource AccentButtonStyle}"
|
||||
PrimaryButtonText="Save">
|
||||
<controls:UnifiedMappingControl x:Name="UnifiedMappingControl" Margin="0,16,0,0" />
|
||||
</ContentDialog>
|
||||
|
||||
<!-- Confirmation Dialog for delete -->
|
||||
<ContentDialog
|
||||
x:Name="DeleteConfirmationDialog"
|
||||
Title="Are you sure?"
|
||||
CloseButtonText="Cancel"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonText="Delete">
|
||||
<TextBlock Text="You are about to delete this remapping." TextWrapping="Wrap" />
|
||||
</ContentDialog>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,525 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Page
|
||||
x:Class="KeyboardManagerEditorUI.Pages.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:commoncontrols="using:Microsoft.PowerToys.Common.UI.Controls"
|
||||
xmlns:controls="using:KeyboardManagerEditorUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:helper="using:KeyboardManagerEditorUI.Helpers"
|
||||
xmlns:local="using:KeyboardManagerEditorUI.Pages"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Page.Resources>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">800</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxHeight">800</x:Double>
|
||||
<Style
|
||||
x:Key="OriginalKeyVisualStyle"
|
||||
BasedOn="{StaticResource DefaultKeyVisualStyle}"
|
||||
TargetType="commoncontrols:KeyVisual">
|
||||
<Setter Property="Padding" Value="6" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Background" Value="{ThemeResource ControlFillColorDefaultBrush}" />
|
||||
<Setter Property="CornerRadius" Value="{StaticResource ControlCornerRadius}" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="RenderKeyAsGlyph" Value="True" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="RemappedKeyVisualStyle"
|
||||
BasedOn="{StaticResource OriginalKeyVisualStyle}"
|
||||
TargetType="commoncontrols:KeyVisual">
|
||||
<Setter Property="Background" Value="{ThemeResource CustomAccentBackgroundBrush}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource AccentTextFillColorPrimaryBrush}" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="RemappedIconLabelControlStyle"
|
||||
BasedOn="{StaticResource DefaultIconLabelControlStyle}"
|
||||
TargetType="controls:IconLabelControl">
|
||||
<Setter Property="Background" Value="{ThemeResource CustomAccentBackgroundBrush}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="6" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="CornerRadius" Value="{StaticResource ControlCornerRadius}" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource AccentTextFillColorPrimaryBrush}" />
|
||||
</Style>
|
||||
<Style x:Key="ItemDividerStyle" TargetType="Rectangle">
|
||||
<Style.Setters>
|
||||
<Setter Property="Grid.ColumnSpan" Value="2" />
|
||||
<Setter Property="Height" Value="1" />
|
||||
<Setter Property="Margin" Value="-16,0,-16,-8" />
|
||||
<Setter Property="Fill" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalAlignment" Value="Bottom" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
<tkconverters:DoubleToVisibilityConverter
|
||||
x:Key="CountToVisibilityConverter"
|
||||
FalseValue="Collapsed"
|
||||
GreaterThan="0"
|
||||
TrueValue="Visible" />
|
||||
<tkconverters:StringVisibilityConverter
|
||||
x:Key="StringVisibilityConverter"
|
||||
EmptyValue="Collapsed"
|
||||
NotEmptyValue="Visible" />
|
||||
</Page.Resources>
|
||||
|
||||
<Grid Padding="16" RowSpacing="16">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="48" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid VerticalAlignment="Top">
|
||||
<Button
|
||||
x:Name="NewRemappingBtn"
|
||||
VerticalAlignment="Top"
|
||||
Click="NewRemappingBtn_Click">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<FontIcon FontSize="14" Glyph="" />
|
||||
<TextBlock VerticalAlignment="Center" Text="Add new remapping" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</Grid>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Background="{ThemeResource LayerFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{ThemeResource OverlayCornerRadius}">
|
||||
<tkcontrols:SwitchPresenter
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
TargetType="x:String"
|
||||
Value="{x:Bind MappingState, Mode=OneWay}">
|
||||
<tkcontrols:Case Value="Empty">
|
||||
<StackPanel
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="8">
|
||||
<FontIcon
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="24"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Glyph="" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
CharacterSpacing="12"
|
||||
Text="Nothing mapped yet"
|
||||
TextAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="NoWrap" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="Create a key or shortcut remapping to customize how your keyboard works."
|
||||
TextAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="NoWrap" />
|
||||
</StackPanel>
|
||||
</tkcontrols:Case>
|
||||
<tkcontrols:Case Value="HasMappings">
|
||||
<ScrollViewer VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto">
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical" Spacing="24">
|
||||
<!-- Remappings Section -->
|
||||
<StackPanel Orientation="Vertical" Visibility="{x:Bind RemappingList.Count, Mode=OneWay, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
<TextBlock
|
||||
Margin="16,16,0,8"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Keys and shortcuts" />
|
||||
<Rectangle
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<ListView
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="RemappingsList_ItemClick"
|
||||
ItemsSource="{x:Bind RemappingList}"
|
||||
ScrollViewer.VerticalScrollMode="Disabled"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="helper:Remapping">
|
||||
<Grid MinHeight="48" Padding="0,8,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Rectangle Style="{StaticResource ItemDividerStyle}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ItemsControl VerticalAlignment="Center" ItemsSource="{x:Bind Shortcut}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<commoncontrols:KeyVisual Content="{Binding}" Style="{StaticResource OriginalKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="maps to" />
|
||||
<ItemsControl VerticalAlignment="Center" ItemsSource="{x:Bind RemappedKeys}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<commoncontrols:KeyVisual Content="{Binding}" Style="{StaticResource RemappedKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind AppName, Converter={StaticResource StringVisibilityConverter}}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="in" />
|
||||
<controls:IconLabelControl ActionType="Program" Label="{x:Bind AppName}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<ToggleSwitch
|
||||
IsOn="{x:Bind IsActive}"
|
||||
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}"
|
||||
Toggled="ToggleSwitch_Toggled" />
|
||||
<Button
|
||||
VerticalAlignment="Center"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
Click="DeleteMapping_Click"
|
||||
Icon="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Tag="{x:Bind}"
|
||||
Text="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Text Section -->
|
||||
<StackPanel Orientation="Vertical" Visibility="{x:Bind TextMappings.Count, Mode=OneWay, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
<TextBlock
|
||||
Margin="16,16,0,8"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Text" />
|
||||
<Rectangle
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<ListView
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="TextMappingsList_ItemClick"
|
||||
ItemsSource="{x:Bind TextMappings}"
|
||||
ScrollViewer.VerticalScrollMode="Disabled"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="helper:TextMapping">
|
||||
<Grid MinHeight="48" Padding="0,8,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Rectangle Style="{StaticResource ItemDividerStyle}" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ItemsControl VerticalAlignment="Center" ItemsSource="{x:Bind Shortcut}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<commoncontrols:KeyVisual Content="{Binding}" Style="{StaticResource OriginalKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="inserts" />
|
||||
<controls:IconLabelControl
|
||||
ActionType="Text"
|
||||
Label="{x:Bind Text}"
|
||||
Style="{StaticResource RemappedIconLabelControlStyle}" />
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind AppName, Converter={StaticResource StringVisibilityConverter}}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="in" />
|
||||
<controls:IconLabelControl ActionType="Program" Label="{x:Bind AppName}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<ToggleSwitch
|
||||
IsOn="{x:Bind IsActive}"
|
||||
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}"
|
||||
Toggled="ToggleSwitch_Toggled" />
|
||||
<Button
|
||||
VerticalAlignment="Center"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
Click="DeleteMapping_Click"
|
||||
Icon="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Tag="{x:Bind}"
|
||||
Text="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Programs Section -->
|
||||
<StackPanel Orientation="Vertical" Visibility="{x:Bind ProgramShortcuts.Count, Mode=OneWay, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
<TextBlock
|
||||
Margin="16,16,0,8"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Programs" />
|
||||
<Rectangle
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
|
||||
<ListView
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="ProgramShortcutsList_ItemClick"
|
||||
ItemsSource="{x:Bind ProgramShortcuts}"
|
||||
ScrollViewer.VerticalScrollMode="Disabled"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="helper:ProgramShortcut">
|
||||
<Grid MinHeight="48" Padding="0,8,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Rectangle Style="{StaticResource ItemDividerStyle}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ItemsControl VerticalAlignment="Center" ItemsSource="{x:Bind Shortcut}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<commoncontrols:KeyVisual Content="{Binding}" Style="{StaticResource OriginalKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="opens" />
|
||||
<controls:IconLabelControl
|
||||
ActionType="Program"
|
||||
Label="{x:Bind AppToRun}"
|
||||
Style="{StaticResource RemappedIconLabelControlStyle}" />
|
||||
<!-- TO DO: Add a ToolTip or Flyout with some of the important advanced info like args -->
|
||||
<!-- {x:Bind Args} -->
|
||||
<!--<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind AppName, Converter={StaticResource StringVisibilityConverter}}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="in" />
|
||||
<kbmcontrols:IconLabelControl ActionType="Program" Label="{x:Bind AppName}" />
|
||||
</StackPanel>-->
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<ToggleSwitch
|
||||
IsOn="{x:Bind IsActive}"
|
||||
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}"
|
||||
Toggled="ToggleSwitch_Toggled" />
|
||||
<Button
|
||||
VerticalAlignment="Center"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
Click="DeleteMapping_Click"
|
||||
Icon="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Tag="{x:Bind}"
|
||||
Text="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
|
||||
<!-- URLs Section -->
|
||||
<StackPanel Orientation="Vertical" Visibility="{x:Bind UrlShortcuts.Count, Mode=OneWay, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
<TextBlock
|
||||
Margin="16,16,0,8"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Urls" />
|
||||
<Rectangle
|
||||
Height="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{ThemeResource CardStrokeColorDefaultBrush}" />
|
||||
<ListView
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="UrlShortcutsList_ItemClick"
|
||||
ItemsSource="{x:Bind UrlShortcuts}"
|
||||
ScrollViewer.VerticalScrollMode="Disabled"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="helper:URLShortcut">
|
||||
<Grid MinHeight="48" Padding="0,8,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Rectangle Style="{StaticResource ItemDividerStyle}" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<ItemsControl VerticalAlignment="Center" ItemsSource="{x:Bind Shortcut}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<commoncontrols:KeyVisual Content="{Binding}" Style="{StaticResource OriginalKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="opens" />
|
||||
<controls:IconLabelControl
|
||||
ActionType="Url"
|
||||
Label="{x:Bind URL}"
|
||||
Style="{StaticResource RemappedIconLabelControlStyle}" />
|
||||
<!--<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind AppName, Converter={StaticResource StringVisibilityConverter}}">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="in" />
|
||||
<controls:IconLabelControl ActionType="Program" Label="{x:Bind AppName}" />
|
||||
</StackPanel>-->
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<ToggleSwitch
|
||||
IsOn="{x:Bind IsActive}"
|
||||
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}"
|
||||
Toggled="ToggleSwitch_Toggled" />
|
||||
<Button
|
||||
VerticalAlignment="Center"
|
||||
Content="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem
|
||||
Click="DeleteMapping_Click"
|
||||
Icon="{ui:FontIcon Glyph=,
|
||||
FontSize=14}"
|
||||
Tag="{x:Bind}"
|
||||
Text="Delete" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</tkcontrols:Case>
|
||||
</tkcontrols:SwitchPresenter>
|
||||
</Grid>
|
||||
|
||||
<!-- Content Dialog for new remapping -->
|
||||
<ContentDialog
|
||||
x:Name="RemappingDialog"
|
||||
Title="Add new remapping"
|
||||
Width="760"
|
||||
MinWidth="800"
|
||||
MinHeight="500"
|
||||
MaxWidth="900"
|
||||
CloseButtonText="Cancel"
|
||||
DefaultButton="Primary"
|
||||
IsPrimaryButtonEnabled="False"
|
||||
PrimaryButtonStyle="{StaticResource AccentButtonStyle}"
|
||||
PrimaryButtonText="Save">
|
||||
<controls:UnifiedMappingControl x:Name="UnifiedMappingControl" Margin="0,16,0,0" />
|
||||
</ContentDialog>
|
||||
|
||||
<!-- Confirmation Dialog for delete -->
|
||||
<ContentDialog
|
||||
x:Name="DeleteConfirmationDialog"
|
||||
Title="Are you sure?"
|
||||
CloseButtonText="Cancel"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonText="Delete">
|
||||
<TextBlock Text="You are about to delete this remapping." TextWrapping="Wrap" />
|
||||
</ContentDialog>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -24,7 +25,7 @@ namespace KeyboardManagerEditorUI.Pages
|
||||
/// A consolidated page that displays all mappings from Remappings, Text, Programs, and URLs pages.
|
||||
/// </summary>
|
||||
#pragma warning disable SA1124 // Do not use regions
|
||||
public sealed partial class All : Page, IDisposable
|
||||
public sealed partial class MainPage : Page, IDisposable, INotifyPropertyChanged
|
||||
{
|
||||
private KeyboardMappingService? _mappingService;
|
||||
private bool _disposed;
|
||||
@@ -33,6 +34,26 @@ namespace KeyboardManagerEditorUI.Pages
|
||||
private bool _isEditMode;
|
||||
private EditingItem? _editingItem;
|
||||
|
||||
private string _mappingState = "Empty";
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current mapping state for the SwitchPresenter: "HasMappings" or "Empty".
|
||||
/// </summary>
|
||||
public string MappingState
|
||||
{
|
||||
get => _mappingState;
|
||||
private set
|
||||
{
|
||||
if (_mappingState != value)
|
||||
{
|
||||
_mappingState = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MappingState)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<Remapping> RemappingList { get; } = new ObservableCollection<Remapping>();
|
||||
|
||||
public ObservableCollection<TextMapping> TextMappings { get; } = new ObservableCollection<TextMapping>();
|
||||
@@ -68,7 +89,7 @@ namespace KeyboardManagerEditorUI.Pages
|
||||
public bool IsAllApps { get; set; } = true;
|
||||
}
|
||||
|
||||
public All()
|
||||
public MainPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
@@ -79,7 +100,7 @@ namespace KeyboardManagerEditorUI.Pages
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed to initialize KeyboardMappingService in All page: " + ex.Message);
|
||||
Logger.LogError("Failed to initialize KeyboardMappingService in MainPage page: " + ex.Message);
|
||||
}
|
||||
|
||||
this.Unloaded += All_Unloaded;
|
||||
@@ -215,11 +236,16 @@ namespace KeyboardManagerEditorUI.Pages
|
||||
// Hook up the primary button click handler
|
||||
RemappingDialog.PrimaryButtonClick += RemappingDialog_PrimaryButtonClick;
|
||||
|
||||
// Hook up real-time validation
|
||||
UnifiedMappingControl.ValidationStateChanged += UnifiedMappingControl_ValidationStateChanged;
|
||||
RemappingDialog.IsPrimaryButtonEnabled = UnifiedMappingControl.IsInputComplete();
|
||||
|
||||
// Show the dialog
|
||||
await RemappingDialog.ShowAsync();
|
||||
|
||||
// Unhook the handler
|
||||
// Unhook the handlers
|
||||
RemappingDialog.PrimaryButtonClick -= RemappingDialog_PrimaryButtonClick;
|
||||
UnifiedMappingControl.ValidationStateChanged -= UnifiedMappingControl_ValidationStateChanged;
|
||||
|
||||
// Reset edit mode
|
||||
_isEditMode = false;
|
||||
@@ -229,6 +255,36 @@ namespace KeyboardManagerEditorUI.Pages
|
||||
KeyboardHookHelper.Instance.CleanupHook();
|
||||
}
|
||||
|
||||
private void UnifiedMappingControl_ValidationStateChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (!UnifiedMappingControl.IsInputComplete())
|
||||
{
|
||||
RemappingDialog.IsPrimaryButtonEnabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Run full validation (self-mapping, illegal shortcuts, etc.) when inputs are complete
|
||||
if (_mappingService != null)
|
||||
{
|
||||
var actionType = UnifiedMappingControl.CurrentActionType;
|
||||
List<string> triggerKeys = UnifiedMappingControl.GetTriggerKeys();
|
||||
|
||||
if (triggerKeys != null && triggerKeys.Count > 0)
|
||||
{
|
||||
ValidationErrorType error = ValidateMapping(actionType, triggerKeys);
|
||||
if (error != ValidationErrorType.NoError)
|
||||
{
|
||||
UnifiedMappingControl.ShowValidationErrorFromType(error);
|
||||
RemappingDialog.IsPrimaryButtonEnabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnifiedMappingControl.HideValidationMessage();
|
||||
RemappingDialog.IsPrimaryButtonEnabled = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Save Logic
|
||||
@@ -348,9 +404,20 @@ namespace KeyboardManagerEditorUI.Pages
|
||||
_isEditMode);
|
||||
|
||||
case UnifiedMappingControl.ActionType.OpenUrl:
|
||||
case UnifiedMappingControl.ActionType.OpenApp:
|
||||
return ValidationHelper.ValidateProgramOrUrlMapping(
|
||||
string urlContent = UnifiedMappingControl.GetUrl();
|
||||
return ValidationHelper.ValidateUrlMapping(
|
||||
triggerKeys,
|
||||
urlContent,
|
||||
isAppSpecific,
|
||||
appName,
|
||||
_mappingService!,
|
||||
_isEditMode);
|
||||
|
||||
case UnifiedMappingControl.ActionType.OpenApp:
|
||||
string programPath = UnifiedMappingControl.GetProgramPath();
|
||||
return ValidationHelper.ValidateAppMapping(
|
||||
triggerKeys,
|
||||
programPath,
|
||||
isAppSpecific,
|
||||
appName,
|
||||
_mappingService!,
|
||||
@@ -620,6 +687,7 @@ namespace KeyboardManagerEditorUI.Pages
|
||||
Logger.LogWarning($"Failed to delete remapping: {string.Join("+", remapping.Shortcut)}");
|
||||
}
|
||||
|
||||
UpdateHasAnyMappings();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -748,6 +816,16 @@ namespace KeyboardManagerEditorUI.Pages
|
||||
LoadTextMappings();
|
||||
LoadProgramShortcuts();
|
||||
LoadUrlShortcuts();
|
||||
UpdateHasAnyMappings();
|
||||
}
|
||||
|
||||
private void UpdateHasAnyMappings()
|
||||
{
|
||||
bool hasAny = RemappingList.Count > 0
|
||||
|| TextMappings.Count > 0
|
||||
|| ProgramShortcuts.Count > 0
|
||||
|| UrlShortcuts.Count > 0;
|
||||
MappingState = hasAny ? "HasMappings" : "Empty";
|
||||
}
|
||||
|
||||
private void LoadRemappings()
|
||||
Reference in New Issue
Block a user