Files
PowerToys/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/ContextMenu.xaml
Michael Jolley 6642c805b7 Context menu cleanup (#40584)
Addressing items in #40583

- [x] When navigating the context menu with the up/down keys, separators
should not be selectable.
- [x] [For context items with a super long title, we need to trim those
with an ellipsis. Ideally, we'd show a tooltip for just those
items.](https://github.com/microsoft/PowerToys/issues/40313)
- [x] [Context menu search bar text size doesn't update after changing
system text size](https://github.com/microsoft/PowerToys/issues/39648)
- [x] Weird "kick out" on first context menu item
- [x] [Primary button doesn't work if the command has more items (fix
regression)](https://github.com/microsoft/PowerToys/issues/40624)

Example of long context menu item titles with tooltips: (@niels9001,
look okay?)


https://github.com/user-attachments/assets/fc0a4034-9c22-48ee-a3f0-44fcc2f294a6

closes #40624
2025-07-16 06:25:24 -05:00

181 lines
9.1 KiB
XML

<?xml version="1.0" encoding="utf-8" ?>
<UserControl
x:Class="Microsoft.CmdPal.UI.Controls.ContextMenu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
xmlns:cmdpalUI="using:Microsoft.CmdPal.UI"
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
xmlns:coreViewModels="using:Microsoft.CmdPal.Core.ViewModels"
xmlns:cpcontrols="using:Microsoft.CmdPal.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:help="using:Microsoft.CmdPal.UI.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkit="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:viewModels="using:Microsoft.CmdPal.UI.ViewModels"
Background="Transparent"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<cmdpalUI:KeyChordToStringConverter x:Key="KeyChordToStringConverter" />
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<cmdpalUI:ContextItemTemplateSelector
x:Key="ContextItemTemplateSelector"
Critical="{StaticResource CriticalContextMenuViewModelTemplate}"
Default="{StaticResource DefaultContextMenuViewModelTemplate}"
Separator="{StaticResource SeparatorContextMenuViewModelTemplate}" />
<!-- Template for context items in the context item menu -->
<DataTemplate x:Key="DefaultContextMenuViewModelTemplate" x:DataType="coreViewModels:CommandContextItemViewModel">
<Grid AutomationProperties.Name="{x:Bind Title}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<cpcontrols:IconBox
Width="16"
Height="16"
Margin="4,0,0,0"
HorizontalAlignment="Left"
SourceKey="{x:Bind Icon}"
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}" />
<TextBlock
x:Name="TitleTextBlock"
Grid.Column="1"
MaxWidth="200"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{x:Bind Title}"
TextTrimming="WordEllipsis"
TextWrapping="NoWrap">
<ToolTipService.ToolTip>
<ToolTip Content="{x:Bind Title}" Visibility="{Binding IsTextTrimmed, ElementName=TitleTextBlock, Converter={StaticResource BoolToVisibilityConverter}}" />
</ToolTipService.ToolTip>
</TextBlock>
<TextBlock
Grid.Column="2"
Margin="16,0,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Foreground="{ThemeResource MenuFlyoutItemKeyboardAcceleratorTextForeground}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind RequestedShortcut, Converter={StaticResource KeyChordToStringConverter}}" />
</Grid>
</DataTemplate>
<!-- Template for context items flagged as critical -->
<DataTemplate x:Key="CriticalContextMenuViewModelTemplate" x:DataType="coreViewModels:CommandContextItemViewModel">
<Grid AutomationProperties.Name="{x:Bind Title}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<cpcontrols:IconBox
Width="16"
Height="16"
Margin="4,0,0,0"
HorizontalAlignment="Left"
Foreground="{ThemeResource SystemFillColorCriticalBrush}"
SourceKey="{x:Bind Icon}"
SourceRequested="{x:Bind help:IconCacheProvider.SourceRequested}" />
<TextBlock
x:Name="TitleTextBlock"
Grid.Column="1"
MaxWidth="200"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Style="{StaticResource ContextItemTitleTextBlockCriticalStyle}"
Text="{x:Bind Title}"
TextTrimming="WordEllipsis"
TextWrapping="NoWrap">
<ToolTipService.ToolTip>
<ToolTip Content="{x:Bind Title}" Visibility="{Binding IsTextTrimmed, ElementName=TitleTextBlock, Converter={StaticResource BoolToVisibilityConverter}}" />
</ToolTipService.ToolTip>
</TextBlock>
<TextBlock
Grid.Column="2"
Margin="16,0,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Style="{StaticResource ContextItemCaptionTextBlockCriticalStyle}"
Text="{x:Bind RequestedShortcut, Converter={StaticResource KeyChordToStringConverter}}" />
</Grid>
</DataTemplate>
<!-- Template for context item separators -->
<DataTemplate x:Key="SeparatorContextMenuViewModelTemplate" x:DataType="coreViewModels:SeparatorContextItemViewModel">
<Rectangle
Height="1"
Margin="-16,-12,-12,-12"
Fill="{ThemeResource MenuFlyoutSeparatorThemeBrush}" />
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="ContextMenuGrid">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel x:Name="CommandsPanel">
<ListView
x:Name="CommandsDropdown"
MinWidth="248"
IsItemClickEnabled="True"
ItemClick="CommandsDropdown_ItemClick"
ItemTemplateSelector="{StaticResource ContextItemTemplateSelector}"
ItemsSource="{x:Bind ViewModel.FilteredItems, Mode=OneWay}"
KeyDown="CommandsDropdown_KeyDown"
SelectionMode="Single">
<ListView.ItemContainerStyle>
<Style BasedOn="{StaticResource DefaultListViewItemStyle}" TargetType="ListViewItem">
<Setter Property="MinHeight" Value="0" />
<Setter Property="Padding" Value="12,8" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemContainerTransitions>
<TransitionCollection />
</ListView.ItemContainerTransitions>
</ListView>
</StackPanel>
<TextBox
x:Name="ContextFilterBox"
x:Uid="ContextFilterBox"
Margin="4"
IsTextScaleFactorEnabled="True"
KeyDown="ContextFilterBox_KeyDown"
PreviewKeyDown="ContextFilterBox_PreviewKeyDown"
TextChanged="ContextFilterBox_TextChanged" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ContextMenuOrder">
<VisualState x:Name="FilterOnTop">
<VisualState.StateTriggers>
<ui:IsEqualStateTrigger Value="{x:Bind ViewModel.FilterOnTop, Mode=OneWay}" To="True" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="CommandsPanel.(Grid.Row)" Value="1" />
<Setter Target="ContextFilterBox.(Grid.Row)" Value="0" />
<Setter Target="CommandsDropdown.Margin" Value="0, 0, 0, 4" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="FilterOnBottom">
<VisualState.StateTriggers>
<ui:IsEqualStateTrigger Value="{x:Bind ViewModel.FilterOnTop, Mode=OneWay}" To="False" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="CommandsPanel.(Grid.Row)" Value="0" />
<Setter Target="ContextFilterBox.(Grid.Row)" Value="1" />
<Setter Target="CommandsDropdown.Margin" Value="0, 4, 0, 0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</UserControl>