Skip to content

Commit 93cd0f6

Browse files
committed
feat: Replace Quick Accent toolbar position dropdown with 3x3 visual grid
Closes #44111 Replaced the ComboBox dropdown for toolbar position selection with a visual 3x3 grid of tiles, making it easier to select positions intuitively. Changes: - Added IndexToBoolConverter for int-to-bool binding conversion - Created PositionRadioButtonStyle with accent color highlighting - Replaced ComboBox with 3x3 Grid of styled RadioButtons - Each tile shows position with tooltip for accessibility The grid layout visually represents the 9 toolbar positions: +----+----+----+ | TL | TC | TR | +----+----+----+ | L | C | R | +----+----+----+ | BL | BC | BR | +----+----+----+
1 parent e68526b commit 93cd0f6

File tree

2 files changed

+164
-11
lines changed

2 files changed

+164
-11
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) Microsoft Corporation
2+
// The Microsoft Corporation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using Microsoft.UI.Xaml.Data;
7+
8+
namespace Microsoft.PowerToys.Settings.UI.Converters
9+
{
10+
/// <summary>
11+
/// Converts an integer index to a boolean value for use with RadioButton groups.
12+
/// The ConverterParameter specifies which index value should return true.
13+
/// </summary>
14+
public partial class IndexToBoolConverter : IValueConverter
15+
{
16+
public object Convert(object value, Type targetType, object parameter, string language)
17+
{
18+
if (value == null || parameter == null)
19+
{
20+
return false;
21+
}
22+
23+
if (value is int intValue && int.TryParse(parameter.ToString(), out int paramIndex))
24+
{
25+
return intValue == paramIndex;
26+
}
27+
28+
return false;
29+
}
30+
31+
public object ConvertBack(object value, Type targetType, object parameter, string language)
32+
{
33+
if (value is bool isChecked && isChecked && parameter != null)
34+
{
35+
if (int.TryParse(parameter.ToString(), out int paramIndex))
36+
{
37+
return paramIndex;
38+
}
39+
}
40+
41+
// Return -1 to indicate no change (RadioButton unchecked)
42+
return -1;
43+
}
44+
}
45+
}

src/settings-ui/Settings.UI/SettingsXAML/Views/PowerAccentPage.xaml

Lines changed: 119 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
55
xmlns:Lib="using:Microsoft.PowerToys.Settings.UI.Library"
66
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
7+
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
78
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
89
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Helpers"
910
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -12,6 +13,54 @@
1213
AutomationProperties.LandmarkType="Main"
1314
mc:Ignorable="d">
1415
<local:NavigablePage.Resources>
16+
<converters:IndexToBoolConverter x:Key="IndexToBoolConverter" />
17+
<Style x:Key="PositionRadioButtonStyle" TargetType="RadioButton">
18+
<Setter Property="MinWidth" Value="32"/>
19+
<Setter Property="MinHeight" Value="32"/>
20+
<Setter Property="Padding" Value="0"/>
21+
<Setter Property="Margin" Value="2"/>
22+
<Setter Property="HorizontalAlignment" Value="Stretch"/>
23+
<Setter Property="VerticalAlignment" Value="Stretch"/>
24+
<Setter Property="Template">
25+
<Setter.Value>
26+
<ControlTemplate TargetType="RadioButton">
27+
<Grid x:Name="RootGrid" Background="{ThemeResource ControlFillColorDefaultBrush}"
28+
BorderBrush="{ThemeResource ControlStrokeColorDefaultBrush}"
29+
BorderThickness="1" CornerRadius="4">
30+
<VisualStateManager.VisualStateGroups>
31+
<VisualStateGroup x:Name="CheckStates">
32+
<VisualState x:Name="Checked">
33+
<VisualState.Setters>
34+
<Setter Target="RootGrid.Background" Value="{ThemeResource AccentFillColorDefaultBrush}"/>
35+
<Setter Target="RootGrid.BorderBrush" Value="{ThemeResource AccentFillColorDefaultBrush}"/>
36+
<Setter Target="CheckMark.Visibility" Value="Visible"/>
37+
</VisualState.Setters>
38+
</VisualState>
39+
<VisualState x:Name="Unchecked"/>
40+
<VisualState x:Name="Indeterminate"/>
41+
</VisualStateGroup>
42+
<VisualStateGroup x:Name="CommonStates">
43+
<VisualState x:Name="Normal"/>
44+
<VisualState x:Name="PointerOver">
45+
<VisualState.Setters>
46+
<Setter Target="RootGrid.Background" Value="{ThemeResource ControlFillColorSecondaryBrush}"/>
47+
</VisualState.Setters>
48+
</VisualState>
49+
<VisualState x:Name="Pressed">
50+
<VisualState.Setters>
51+
<Setter Target="RootGrid.Background" Value="{ThemeResource ControlFillColorTertiaryBrush}"/>
52+
</VisualState.Setters>
53+
</VisualState>
54+
</VisualStateGroup>
55+
</VisualStateManager.VisualStateGroups>
56+
<Ellipse x:Name="CheckMark" Width="8" Height="8"
57+
Fill="{ThemeResource TextOnAccentFillColorPrimaryBrush}"
58+
Visibility="Collapsed"/>
59+
</Grid>
60+
</ControlTemplate>
61+
</Setter.Value>
62+
</Setter>
63+
</Style>
1564
<CollectionViewSource
1665
x:Name="LanguagesCustomViewSource"
1766
IsSourceGrouped="True"
@@ -154,17 +203,76 @@
154203
Name="QuickAccentToolbarPosition"
155204
x:Uid="QuickAccent_ToolbarPosition"
156205
HeaderIcon="{ui:FontIcon Glyph=&#xEC12;}">
157-
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay}">
158-
<ComboBoxItem x:Uid="QuickAccent_ToolbarPosition_TopCenter" />
159-
<ComboBoxItem x:Uid="QuickAccent_ToolbarPosition_BottomCenter" />
160-
<ComboBoxItem x:Uid="QuickAccent_ToolbarPosition_Left" />
161-
<ComboBoxItem x:Uid="QuickAccent_ToolbarPosition_Right" />
162-
<ComboBoxItem x:Uid="QuickAccent_ToolbarPosition_TopRightCorner" />
163-
<ComboBoxItem x:Uid="QuickAccent_ToolbarPosition_TopLeftCorner" />
164-
<ComboBoxItem x:Uid="QuickAccent_ToolbarPosition_BottomRightCorner" />
165-
<ComboBoxItem x:Uid="QuickAccent_ToolbarPosition_BottomLeftCorner" />
166-
<ComboBoxItem x:Uid="QuickAccent_ToolbarPosition_Center" />
167-
</ComboBox>
206+
<!-- 3x3 Grid for toolbar position selection -->
207+
<Grid Width="108" Height="108">
208+
<Grid.RowDefinitions>
209+
<RowDefinition Height="*"/>
210+
<RowDefinition Height="*"/>
211+
<RowDefinition Height="*"/>
212+
</Grid.RowDefinitions>
213+
<Grid.ColumnDefinitions>
214+
<ColumnDefinition Width="*"/>
215+
<ColumnDefinition Width="*"/>
216+
<ColumnDefinition Width="*"/>
217+
</Grid.ColumnDefinitions>
218+
219+
<!-- Top Left (index 5) -->
220+
<RadioButton Grid.Row="0" Grid.Column="0" GroupName="ToolbarPosition"
221+
IsChecked="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay, Converter={StaticResource IndexToBoolConverter}, ConverterParameter=5}"
222+
Style="{StaticResource PositionRadioButtonStyle}"
223+
AutomationProperties.Name="Top left corner"
224+
ToolTipService.ToolTip="Top left corner"/>
225+
<!-- Top Center (index 0) -->
226+
<RadioButton Grid.Row="0" Grid.Column="1" GroupName="ToolbarPosition"
227+
IsChecked="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay, Converter={StaticResource IndexToBoolConverter}, ConverterParameter=0}"
228+
Style="{StaticResource PositionRadioButtonStyle}"
229+
AutomationProperties.Name="Top center"
230+
ToolTipService.ToolTip="Top center"/>
231+
<!-- Top Right (index 4) -->
232+
<RadioButton Grid.Row="0" Grid.Column="2" GroupName="ToolbarPosition"
233+
IsChecked="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay, Converter={StaticResource IndexToBoolConverter}, ConverterParameter=4}"
234+
Style="{StaticResource PositionRadioButtonStyle}"
235+
AutomationProperties.Name="Top right corner"
236+
ToolTipService.ToolTip="Top right corner"/>
237+
238+
<!-- Left (index 2) -->
239+
<RadioButton Grid.Row="1" Grid.Column="0" GroupName="ToolbarPosition"
240+
IsChecked="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay, Converter={StaticResource IndexToBoolConverter}, ConverterParameter=2}"
241+
Style="{StaticResource PositionRadioButtonStyle}"
242+
AutomationProperties.Name="Left"
243+
ToolTipService.ToolTip="Left"/>
244+
<!-- Center (index 8) -->
245+
<RadioButton Grid.Row="1" Grid.Column="1" GroupName="ToolbarPosition"
246+
IsChecked="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay, Converter={StaticResource IndexToBoolConverter}, ConverterParameter=8}"
247+
Style="{StaticResource PositionRadioButtonStyle}"
248+
AutomationProperties.Name="Center"
249+
ToolTipService.ToolTip="Center"/>
250+
<!-- Right (index 3) -->
251+
<RadioButton Grid.Row="1" Grid.Column="2" GroupName="ToolbarPosition"
252+
IsChecked="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay, Converter={StaticResource IndexToBoolConverter}, ConverterParameter=3}"
253+
Style="{StaticResource PositionRadioButtonStyle}"
254+
AutomationProperties.Name="Right"
255+
ToolTipService.ToolTip="Right"/>
256+
257+
<!-- Bottom Left (index 7) -->
258+
<RadioButton Grid.Row="2" Grid.Column="0" GroupName="ToolbarPosition"
259+
IsChecked="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay, Converter={StaticResource IndexToBoolConverter}, ConverterParameter=7}"
260+
Style="{StaticResource PositionRadioButtonStyle}"
261+
AutomationProperties.Name="Bottom left corner"
262+
ToolTipService.ToolTip="Bottom left corner"/>
263+
<!-- Bottom Center (index 1) -->
264+
<RadioButton Grid.Row="2" Grid.Column="1" GroupName="ToolbarPosition"
265+
IsChecked="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay, Converter={StaticResource IndexToBoolConverter}, ConverterParameter=1}"
266+
Style="{StaticResource PositionRadioButtonStyle}"
267+
AutomationProperties.Name="Bottom center"
268+
ToolTipService.ToolTip="Bottom center"/>
269+
<!-- Bottom Right (index 6) -->
270+
<RadioButton Grid.Row="2" Grid.Column="2" GroupName="ToolbarPosition"
271+
IsChecked="{x:Bind Path=ViewModel.ToolbarPositionIndex, Mode=TwoWay, Converter={StaticResource IndexToBoolConverter}, ConverterParameter=6}"
272+
Style="{StaticResource PositionRadioButtonStyle}"
273+
AutomationProperties.Name="Bottom right corner"
274+
ToolTipService.ToolTip="Bottom right corner"/>
275+
</Grid>
168276
</tkcontrols:SettingsCard>
169277
<tkcontrols:SettingsCard
170278
Name="QuickAccentDescriptionIndicator"

0 commit comments

Comments
 (0)