Browse Source

combobox - fix focus visual clipping and add selection pill to item

pull/21771/head
Emmanuel Hansen 4 weeks ago
parent
commit
6ff1b12fb9
  1. 17
      src/Avalonia.Themes.Fluent2/Controls/ComboBox.xaml
  2. 132
      src/Avalonia.Themes.Fluent2/Controls/ComboBoxItem.xaml

17
src/Avalonia.Themes.Fluent2/Controls/ComboBox.xaml

@ -60,16 +60,6 @@
<CornerRadius x:Key="ComboBoxDropDownButtonBackgroundCornerRadius">4</CornerRadius> <CornerRadius x:Key="ComboBoxDropDownButtonBackgroundCornerRadius">4</CornerRadius>
<StreamGeometry x:Key="ComboBoxDropDownPathData">M4.293 8.293a1 1 0 0 1 1.414 0L12 14.586l6.293-6.293a1 1 0 1 1 1.414 1.414l-7 7a1 1 0 0 1-1.414 0l-7-7a1 1 0 0 1 0-1.414Z</StreamGeometry> <StreamGeometry x:Key="ComboBoxDropDownPathData">M4.293 8.293a1 1 0 0 1 1.414 0L12 14.586l6.293-6.293a1 1 0 1 1 1.414 1.414l-7 7a1 1 0 0 1-1.414 0l-7-7a1 1 0 0 1 0-1.414Z</StreamGeometry>
<ControlTheme TargetType="Rectangle" x:Key="ComboBoxItemPill">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Height" Value="{StaticResource ComboBoxItemPillHeight}" />
<Setter Property="Width" Value="{StaticResource ComboBoxItemPillWidth}" />
<Setter Property="Fill" Value="{StaticResource ComboBoxItemPillFillBrush}" />
<Setter Property="RadiusX" Value="{StaticResource ComboBoxItemPillCornerRadius}" />
<Setter Property="RadiusY" Value="{StaticResource ComboBoxItemPillCornerRadius}" />
<Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
</ControlTheme>
<!-- WinUI reference: ComboBox_themeresources.xaml (DefaultComboBoxStyle), 820 lines. <!-- WinUI reference: ComboBox_themeresources.xaml (DefaultComboBoxStyle), 820 lines.
Closed control is Button-like: ControlFillColorDefault fill with a ControlElevationBorder Closed control is Button-like: ControlFillColorDefault fill with a ControlElevationBorder
(both via the re-pointed ComboBox* aliases), radius 4 (ControlCornerRadius), background (both via the re-pointed ComboBox* aliases), radius 4 (ControlCornerRadius), background
@ -108,10 +98,11 @@
BorderBrush="{DynamicResource ComboBoxBackgroundBorderBrushUnfocused}" BorderBrush="{DynamicResource ComboBoxBackgroundBorderBrushUnfocused}"
BorderThickness="{TemplateBinding BorderThickness}" BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}" CornerRadius="{TemplateBinding CornerRadius}"
IsVisible="False"/> Opacity="0"/>
<Border x:Name="Background" <Border x:Name="Background"
Grid.Column="0" Grid.Column="0"
Grid.ColumnSpan="2" Grid.ColumnSpan="2"
TemplatedControl.IsTemplateFocusTarget="True"
Background="{TemplateBinding Background}" Background="{TemplateBinding Background}"
BackgroundSizing="{TemplateBinding BackgroundSizing}" BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
@ -124,7 +115,7 @@
</Transitions> </Transitions>
</Border.Transitions> </Border.Transitions>
</Border> </Border>
<Rectangle x:Name="Pill" Theme="{DynamicResource ComboBoxItemPill}" Margin="1,0,0,0" Grid.Column="0" Opacity="0"> <Rectangle x:Name="Pill" Theme="{StaticResource ComboBoxItemPill}" Margin="1,0,0,0" Grid.Column="0" Opacity="0">
<Rectangle.RenderTransform> <Rectangle.RenderTransform>
<ScaleTransform ScaleY="1"/> <ScaleTransform ScaleY="1"/>
</Rectangle.RenderTransform> </Rectangle.RenderTransform>
@ -264,7 +255,7 @@
<!-- Focused State --> <!-- Focused State -->
<Style Selector="^:focus-visible"> <Style Selector="^:focus-visible">
<Style Selector="^ /template/ Border#HighlightBackground"> <Style Selector="^ /template/ Border#HighlightBackground">
<Setter Property="IsVisible" Value="True" /> <Setter Property="Opacity" Value="1" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxBackgroundBorderBrushFocused}" /> <Setter Property="BorderBrush" Value="{DynamicResource ComboBoxBackgroundBorderBrushFocused}" />
</Style> </Style>
<Style Selector="^ /template/ Rectangle#Pill"> <Style Selector="^ /template/ Rectangle#Pill">

132
src/Avalonia.Themes.Fluent2/Controls/ComboBoxItem.xaml

@ -16,114 +16,144 @@
</Design.PreviewWith> </Design.PreviewWith>
<!-- WinUI reference: ComboBox_themeresources.xaml (DefaultComboBoxItemStyle + ComboBoxItemPill). <!-- WinUI reference: ComboBox_themeresources.xaml (DefaultComboBoxItemStyle + ComboBoxItemPill).
Items are rounded (ComboBoxItemCornerRadius = 3), inset 5,2 from the dropdown edges Items are rounded (ComboBoxItemCornerRadius = 3), inset 5,2 from the dropdown edges
(LayoutRoot margin in WinUI), padded 11,5,11,7 (ComboBoxItemThemePadding, shared resource), (LayoutRoot margin in WinUI), padded 11,5,11,7 (ComboBoxItemThemePadding, shared resource),
with an accent selection pill (ComboBoxItemPillWidth x ComboBoxItemPillHeight = 3x16, r1.5) with an accent selection pill (ComboBoxItemPillWidth x ComboBoxItemPillHeight = 3x16, r1.5)
whose height WinUI animates over 167ms (ComboBoxItemScaleAnimationDuration). --> whose height WinUI animates over 167ms (ComboBoxItemScaleAnimationDuration). -->
<CornerRadius x:Key="ComboBoxItemCornerRadius">3</CornerRadius> <CornerRadius x:Key="ComboBoxItemCornerRadius">3</CornerRadius>
<x:Double x:Key="ComboBoxItemPillWidth">3</x:Double> <x:Double x:Key="ComboBoxItemPillWidth">3</x:Double>
<x:Double x:Key="ComboBoxItemPillHeight">16</x:Double> <x:Double x:Key="ComboBoxItemPillHeight">16</x:Double>
<x:Double x:Key="ComboBoxItemPillMinScale">0.625</x:Double>
<ControlTheme TargetType="Rectangle" x:Key="ComboBoxItemPill">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Height" Value="{StaticResource ComboBoxItemPillHeight}" />
<Setter Property="Width" Value="{StaticResource ComboBoxItemPillWidth}" />
<Setter Property="Fill" Value="{StaticResource ComboBoxItemPillFillBrush}" />
<Setter Property="RadiusX" Value="{StaticResource ComboBoxItemPillCornerRadius}" />
<Setter Property="RadiusY" Value="{StaticResource ComboBoxItemPillCornerRadius}" />
<Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
</ControlTheme>
<ControlTheme x:Key="{x:Type ComboBoxItem}" TargetType="ComboBoxItem"> <ControlTheme x:Key="{x:Type ComboBoxItem}" TargetType="ComboBoxItem">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForeground}" /> <Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForeground}" />
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackground}" /> <Setter Property="Background" Value="{DynamicResource ComboBoxItemBackground}" />
<Setter Property="Padding" Value="{DynamicResource ComboBoxItemThemePadding}" /> <Setter Property="Padding" Value="{DynamicResource ComboBoxItemThemePadding}" />
<Setter Property="CornerRadius" Value="{DynamicResource ComboBoxItemCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ComboBoxItemCornerRadius}" />
<!--Winui uses system focus visuals, which ignores visual clipping. Avalonia focus visual is clipped by the target, thus we disable clipping on the combobox item and clip instead in the root border-->
<Setter Property="ClipToBounds" Value="False" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" /> <Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<!-- Margin matches WinUI's LayoutRoot margin (5,2,5,2). --> <Border Name="LayoutRoot"
<Panel Margin="5,2,5,2"> Margin="5,2,5,2"
<ContentPresenter Name="PART_ContentPresenter" Background="{TemplateBinding Background}"
Foreground="{TemplateBinding Foreground}" BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}"
BackgroundSizing="InnerBorderEdge" TemplatedControl.IsTemplateFocusTarget="True"
BorderBrush="{TemplateBinding BorderBrush}" ClipToBounds="True"
BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}">
CornerRadius="{TemplateBinding CornerRadius}" <Grid ClipToBounds="True">
ContentTemplate="{TemplateBinding ContentTemplate}" <Rectangle Name="Pill"
Content="{TemplateBinding Content}" Theme="{DynamicResource ComboBoxItemPill}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Opacity="0"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" IsHitTestVisible="False"
Padding="{TemplateBinding Padding}" /> UseLayoutRounding="False"
<!-- Selection pill, scale-animated like the ListBoxItem one. ComboBoxItemPillFillBrush is RenderTransform="scaleY(1)"/>
not aliased in this theme yet, so the Fluent 2 token AccentFillColorDefaultBrush is <ContentPresenter Name="PART_ContentPresenter"
referenced directly. --> Foreground="{TemplateBinding Foreground}"
<Rectangle Name="SelectionIndicator" BackgroundSizing="InnerBorderEdge"
IsVisible="False" ContentTemplate="{TemplateBinding ContentTemplate}"
Width="{DynamicResource ComboBoxItemPillWidth}" Content="{TemplateBinding Content}"
Height="{DynamicResource ComboBoxItemPillHeight}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
RadiusX="1.5" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
RadiusY="1.5" Margin="{TemplateBinding Padding}" />
HorizontalAlignment="Left" </Grid>
VerticalAlignment="Center" </Border>
IsHitTestVisible="False"
UseLayoutRounding="False"
RenderTransform="scaleY(0)"
Fill="{DynamicResource AccentFillColorDefaultBrush}">
<Rectangle.Transitions>
<Transitions>
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.167" Easing="0,0 0,1" />
</Transitions>
</Rectangle.Transitions>
</Rectangle>
</Panel>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
<!-- PointerOver state --> <!-- PointerOver state -->
<Style Selector="^:pointerover /template/ ContentPresenter"> <Style Selector="^:pointerover /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundPointerOver}" /> <Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushPointerOver}" /> <Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushPointerOver}" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundPointerOver}" /> <Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundPointerOver}" />
</Style> </Style>
<!-- Disabled state --> <!-- Disabled state -->
<Style Selector="^:disabled /template/ ContentPresenter"> <Style Selector="^:disabled /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundDisabled}" /> <Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushDisabled}" /> <Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushDisabled}" />
</Style>
<Style Selector="^:disabled /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundDisabled}" /> <Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundDisabled}" />
</Style> </Style>
<!-- Pressed state --> <!-- Pressed state -->
<Style Selector="^:pressed /template/ ContentPresenter"> <Style Selector="^:pressed /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundPressed}" /> <Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushPressed}" /> <Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushPressed}" />
</Style>
<Style Selector="^:pressed /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundPressed}" /> <Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundPressed}" />
</Style> </Style>
<!-- Focused state -->
<Style Selector="^:focus /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelected}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelected}" />
</Style>
<Style Selector="^:focus /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelected}" />
</Style>
<!-- Selected state --> <!-- Selected state -->
<Style Selector="^:selected"> <Style Selector="^:selected">
<Style Selector="^ /template/ ContentPresenter"> <Style Selector="^ /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelected}" /> <Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelected}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelected}" /> <Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelected}" />
</Style>
<Style Selector="^ /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelected}" /> <Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelected}" />
</Style> </Style>
<Style Selector="^ /template/ Rectangle#SelectionIndicator">
<Setter Property="IsVisible" Value="True" /> <Style Selector="^ /template/ Rectangle#Pill">
<Setter Property="RenderTransform" Value="scaleY(1)" /> <Setter Property="Opacity" Value="1" />
</Style> </Style>
<!-- Selected Disabled state --> <!-- Selected Disabled state -->
<Style Selector="^:disabled /template/ ContentPresenter"> <Style Selector="^:disabled /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelectedDisabled}" /> <Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelectedDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelectedDisabled}" /> <Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelectedDisabled}" />
</Style>
<Style Selector="^:disabled /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelectedDisabled}" /> <Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelectedDisabled}" />
</Style> </Style>
<Style Selector="^:disabled /template/ Rectangle#SelectionIndicator"> <Style Selector="^:disabled /template/ Rectangle#Pill">
<Setter Property="Fill" Value="{DynamicResource AccentFillColorDisabledBrush}" /> <Setter Property="Fill" Value="{DynamicResource AccentFillColorDisabledBrush}" />
</Style> </Style>
<!-- Selected PointerOver state --> <!-- Selected PointerOver state -->
<Style Selector="^:pointerover /template/ ContentPresenter"> <Style Selector="^:pointerover /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelectedPointerOver}" /> <Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelectedPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelectedPointerOver}" /> <Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelectedPointerOver}" />
</Style>
<Style Selector="^:pointerover /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelectedPointerOver}" /> <Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelectedPointerOver}" />
</Style> </Style>
<!-- Selected Pressed state --> <!-- Selected Pressed state -->
<Style Selector="^:pressed /template/ ContentPresenter"> <Style Selector="^:pressed /template/ Border#LayoutRoot">
<Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelectedPressed}" /> <Setter Property="Background" Value="{DynamicResource ComboBoxItemBackgroundSelectedPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelectedPressed}" /> <Setter Property="BorderBrush" Value="{DynamicResource ComboBoxItemBorderBrushSelectedPressed}" />
</Style>
<Style Selector="^:pressed /template/ ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelectedPressed}" /> <Setter Property="Foreground" Value="{DynamicResource ComboBoxItemForegroundSelectedPressed}" />
</Style> </Style>
<Style Selector="^:pressed /template/ Rectangle#Pill">
<Setter Property="RenderTransform" >
<ScaleTransform ScaleY="{DynamicResource ComboBoxItemPillMinScale}" />
</Setter>
</Style>
</Style> </Style>
</ControlTheme> </ControlTheme>
</ResourceDictionary> </ResourceDictionary>

Loading…
Cancel
Save