Skip to content

Commit 82b0315

Browse files
committed
Stabilize process context menu styling
1 parent d4683bc commit 82b0315

4 files changed

Lines changed: 25 additions & 103 deletions

File tree

Tests/ThreadPilot.Core.Tests/ProcessViewXamlBindingTests.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,11 @@ public void ProcessGridContextMenu_MenuItemsUseStableDetachedMenuStyle()
8383

8484
Assert.Contains("<ContextMenu", serialized, StringComparison.Ordinal);
8585
Assert.Contains("Style=\"{StaticResource ProcessContextMenuStyle}\"", serialized, StringComparison.Ordinal);
86-
Assert.Contains("BasedOn=\"{x:Null}\"", serialized, StringComparison.Ordinal);
8786
Assert.Contains("TargetType=\"{x:Type MenuItem}\"", serialized, StringComparison.Ordinal);
8887
Assert.Contains("FontWeight\" Value=\"Normal\"", serialized, StringComparison.Ordinal);
8988
Assert.Contains("FontSize\" Value=\"{DynamicResource BodyFontSize}\"", serialized, StringComparison.Ordinal);
9089
Assert.Contains("Style=\"{StaticResource ProcessContextMenuItemStyle}\"", serialized, StringComparison.Ordinal);
90+
Assert.DoesNotContain("ControlTemplate TargetType=\"{x:Type MenuItem}\"", serialized, StringComparison.Ordinal);
9191
Assert.DoesNotContain("FontWeight\" Value=\"{Binding", serialized, StringComparison.Ordinal);
9292
Assert.DoesNotContain("FontWeight\" Value=\"{TemplateBinding", serialized, StringComparison.Ordinal);
9393
}
@@ -103,21 +103,22 @@ public void ProcessGridContextMenu_DoesNotApplyMenuItemStyleToSeparators()
103103
Assert.DoesNotContain("<Separator Style=\"{StaticResource ProcessContextMenuItemStyle}\"", serialized, StringComparison.Ordinal);
104104
Assert.Contains("<Separator Style=\"{StaticResource ProcessContextMenuSeparatorStyle}\"", serialized, StringComparison.Ordinal);
105105
Assert.Contains("TargetType=\"{x:Type Separator}\"", serialized, StringComparison.Ordinal);
106+
Assert.DoesNotContain("ControlTemplate TargetType=\"{x:Type Separator}\"", serialized, StringComparison.Ordinal);
106107
}
107108

108109
[Fact]
109-
public void ProcessGridContextMenu_UsesThemeAwareTemplatesWithoutDefaultIconColumn()
110+
public void ProcessGridContextMenu_UsesThemeAwareNativeMenuWithoutCustomTemplates()
110111
{
111112
var document = XDocument.Load(ProcessViewPath, LoadOptions.PreserveWhitespace);
112113
var serialized = document.ToString(SaveOptions.DisableFormatting);
113114

114-
Assert.Contains("ControlTemplate TargetType=\"{x:Type MenuItem}\"", serialized, StringComparison.Ordinal);
115-
Assert.Contains("ControlTemplate TargetType=\"{x:Type Separator}\"", serialized, StringComparison.Ordinal);
116-
Assert.Contains("x:Name=\"SubmenuArrow\"", serialized, StringComparison.Ordinal);
117-
Assert.Contains("QuietRowHoverBackgroundBrush", serialized, StringComparison.Ordinal);
118-
Assert.Contains("TextDisabledBrush", serialized, StringComparison.Ordinal);
115+
Assert.Contains("TargetType=\"{x:Type ContextMenu}\"", serialized, StringComparison.Ordinal);
116+
Assert.Contains("TargetType=\"{x:Type MenuItem}\"", serialized, StringComparison.Ordinal);
117+
Assert.DoesNotContain("BasedOn=\"{x:Null}\"", serialized, StringComparison.Ordinal);
118+
Assert.DoesNotContain("x:Name=\"SubmenuArrow\"", serialized, StringComparison.Ordinal);
119119
Assert.Contains("CardSurfaceBrush", serialized, StringComparison.Ordinal);
120120
Assert.Contains("BorderSubtleBrush", serialized, StringComparison.Ordinal);
121+
Assert.Contains("TextPrimaryBrush", serialized, StringComparison.Ordinal);
121122
Assert.DoesNotContain("IconHost", serialized, StringComparison.Ordinal);
122123
Assert.DoesNotContain("CheckGlyph", serialized, StringComparison.Ordinal);
123124
Assert.DoesNotContain("SystemColors.Menu", serialized, StringComparison.Ordinal);

Tests/ThreadPilot.Core.Tests/SettingsViewModelThemeTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ public void SettingsView_ExposesPersistentRuleAutoApplyToggle()
9494
"SettingsView.xaml");
9595
var serialized = File.ReadAllText(settingsViewPath);
9696

97-
Assert.Contains("Rules &amp; automation", serialized, StringComparison.Ordinal);
98-
Assert.Contains("Apply saved rules when matching processes start", serialized, StringComparison.Ordinal);
97+
Assert.Contains("Text=\"Rules &amp; automation\" Style=\"{StaticResource SectionHeaderStyle}\"", serialized, StringComparison.Ordinal);
98+
Assert.Contains("Text=\"Apply saved rules when matching processes start\"", serialized, StringComparison.Ordinal);
99+
Assert.Contains("TextWrapping=\"Wrap\"", serialized, StringComparison.Ordinal);
99100
Assert.Contains("IsChecked=\"{Binding Settings.ApplyPersistentRulesOnProcessStart}\"", serialized, StringComparison.Ordinal);
100101
Assert.Contains("This does not install a Windows Service and does not use registry/IFEO persistence.", serialized, StringComparison.Ordinal);
101102
}

Views/ProcessView.xaml

Lines changed: 6 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -23,108 +23,26 @@
2323
<sys:Double x:Key="ProcessFontMedium">14</sys:Double>
2424
<sys:Double x:Key="ProcessFontMediumSmall">12</sys:Double>
2525
<sys:Double x:Key="ProcessFontSmall">11</sys:Double>
26-
<Style x:Key="ProcessContextMenuItemStyle" TargetType="{x:Type MenuItem}" BasedOn="{x:Null}">
26+
<Style x:Key="ProcessContextMenuItemStyle" TargetType="{x:Type MenuItem}">
2727
<Setter Property="FontWeight" Value="Normal"/>
2828
<Setter Property="FontSize" Value="{DynamicResource BodyFontSize}"/>
2929
<Setter Property="Foreground" Value="{DynamicResource TextPrimaryBrush}"/>
30-
<Setter Property="Background" Value="Transparent"/>
31-
<Setter Property="BorderBrush" Value="Transparent"/>
3230
<Setter Property="Padding" Value="12,7"/>
3331
<Setter Property="MinWidth" Value="220"/>
34-
<Setter Property="Template">
35-
<Setter.Value>
36-
<ControlTemplate TargetType="{x:Type MenuItem}">
37-
<Border x:Name="MenuItemRoot"
38-
Background="{TemplateBinding Background}"
39-
BorderBrush="{TemplateBinding BorderBrush}"
40-
BorderThickness="0"
41-
SnapsToDevicePixels="True">
42-
<Grid>
43-
<Grid.ColumnDefinitions>
44-
<ColumnDefinition Width="*"/>
45-
<ColumnDefinition Width="Auto"/>
46-
</Grid.ColumnDefinitions>
47-
48-
<ContentPresenter x:Name="HeaderPresenter"
49-
Grid.Column="0"
50-
Margin="{TemplateBinding Padding}"
51-
ContentSource="Header"
52-
RecognizesAccessKey="True"
53-
VerticalAlignment="Center"
54-
TextElement.Foreground="{TemplateBinding Foreground}"/>
55-
56-
<Path x:Name="SubmenuArrow"
57-
Grid.Column="1"
58-
Width="5"
59-
Height="9"
60-
Margin="8,0,12,0"
61-
Data="M 0 0 L 5 4.5 L 0 9 Z"
62-
Fill="{DynamicResource TextSecondaryBrush}"
63-
Stretch="Fill"
64-
VerticalAlignment="Center"
65-
Visibility="Collapsed"/>
66-
67-
<Popup x:Name="PART_Popup"
68-
AllowsTransparency="True"
69-
Focusable="False"
70-
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
71-
Placement="Right"
72-
PopupAnimation="Fade">
73-
<Border Background="{DynamicResource CardSurfaceBrush}"
74-
BorderBrush="{DynamicResource BorderSubtleBrush}"
75-
BorderThickness="1"
76-
Padding="4"
77-
SnapsToDevicePixels="True">
78-
<ScrollViewer CanContentScroll="True"
79-
HorizontalScrollBarVisibility="Disabled"
80-
VerticalScrollBarVisibility="Auto">
81-
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Cycle"
82-
KeyboardNavigation.TabNavigation="Cycle"/>
83-
</ScrollViewer>
84-
</Border>
85-
</Popup>
86-
</Grid>
87-
</Border>
88-
<ControlTemplate.Triggers>
89-
<Trigger Property="HasItems" Value="True">
90-
<Setter TargetName="SubmenuArrow" Property="Visibility" Value="Visible"/>
91-
</Trigger>
92-
<Trigger Property="IsHighlighted" Value="True">
93-
<Setter TargetName="MenuItemRoot" Property="Background" Value="{DynamicResource QuietRowHoverBackgroundBrush}"/>
94-
<Setter TargetName="SubmenuArrow" Property="Fill" Value="{DynamicResource TextPrimaryBrush}"/>
95-
</Trigger>
96-
<Trigger Property="IsSubmenuOpen" Value="True">
97-
<Setter TargetName="MenuItemRoot" Property="Background" Value="{DynamicResource QuietRowHoverBackgroundBrush}"/>
98-
<Setter TargetName="SubmenuArrow" Property="Fill" Value="{DynamicResource TextPrimaryBrush}"/>
99-
</Trigger>
100-
<Trigger Property="IsEnabled" Value="False">
101-
<Setter Property="Foreground" Value="{DynamicResource TextDisabledBrush}"/>
102-
<Setter TargetName="SubmenuArrow" Property="Fill" Value="{DynamicResource TextDisabledBrush}"/>
103-
</Trigger>
104-
</ControlTemplate.Triggers>
105-
</ControlTemplate>
106-
</Setter.Value>
107-
</Setter>
10832
</Style>
109-
<Style x:Key="ProcessContextMenuSeparatorStyle" TargetType="{x:Type Separator}" BasedOn="{x:Null}">
33+
<Style x:Key="ProcessContextMenuSeparatorStyle" TargetType="{x:Type Separator}">
11034
<Setter Property="Background" Value="{DynamicResource BorderSubtleBrush}"/>
11135
<Setter Property="Margin" Value="8,4"/>
112-
<Setter Property="Template">
113-
<Setter.Value>
114-
<ControlTemplate TargetType="{x:Type Separator}">
115-
<Border Height="1"
116-
Background="{DynamicResource BorderSubtleBrush}"
117-
SnapsToDevicePixels="True"/>
118-
</ControlTemplate>
119-
</Setter.Value>
120-
</Setter>
12136
</Style>
122-
<Style x:Key="ProcessContextMenuStyle" TargetType="{x:Type ContextMenu}" BasedOn="{x:Null}">
37+
<Style x:Key="ProcessContextMenuStyle" TargetType="{x:Type ContextMenu}">
12338
<Setter Property="FontWeight" Value="Normal"/>
12439
<Setter Property="FontSize" Value="{DynamicResource BodyFontSize}"/>
12540
<Setter Property="Foreground" Value="{DynamicResource TextPrimaryBrush}"/>
12641
<Setter Property="Background" Value="{DynamicResource CardSurfaceBrush}"/>
12742
<Setter Property="BorderBrush" Value="{DynamicResource BorderSubtleBrush}"/>
43+
<Setter Property="BorderThickness" Value="1"/>
44+
<Setter Property="Padding" Value="4"/>
45+
<Setter Property="SnapsToDevicePixels" Value="True"/>
12846
</Style>
12947
</UserControl.Resources>
13048

Views/SettingsView.xaml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -209,15 +209,17 @@
209209
</Border>
210210
</StackPanel>
211211

212-
<!-- Process Event Settings Section -->
212+
<!-- Rules & automation Section -->
213213
<StackPanel Width="372" Margin="0,0,16,16">
214-
<TextBlock Text="Process Event Settings" Style="{StaticResource SectionHeaderStyle}" Margin="0,0,0,8"/>
214+
<TextBlock Text="Rules &amp; automation" Style="{StaticResource SectionHeaderStyle}" Margin="0,0,0,8"/>
215215
<Border Style="{StaticResource SettingsCardStyle}">
216216
<StackPanel>
217-
<TextBlock Text="Rules &amp; automation" FontWeight="SemiBold" Margin="0,0,0,5"/>
218-
<CheckBox Content="Apply saved rules when matching processes start"
219-
IsChecked="{Binding Settings.ApplyPersistentRulesOnProcessStart}"
220-
Margin="0,0,0,5"/>
217+
<TextBlock Text="Saved rule auto-apply" FontWeight="SemiBold" Margin="0,0,0,5"/>
218+
<CheckBox IsChecked="{Binding Settings.ApplyPersistentRulesOnProcessStart}"
219+
Margin="0,0,0,5">
220+
<TextBlock Text="Apply saved rules when matching processes start"
221+
TextWrapping="Wrap"/>
222+
</CheckBox>
221223
<TextBlock Text="Applies enabled saved rules while ThreadPilot is running. This does not install a Windows Service and does not use registry/IFEO persistence."
222224
Style="{StaticResource DescriptionStyle}"
223225
Margin="20,0,0,15"/>

0 commit comments

Comments
 (0)