Skip to content

Commit c74d656

Browse files
committed
theme: Update HeaderedContentControl theme to properly support headers longer than control width
1 parent aa46bb5 commit c74d656

File tree

3 files changed

+83
-98
lines changed

3 files changed

+83
-98
lines changed

samples/AvaloniaExplorer/OptionsDialog.axaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
Title="Internet Options">
1313
<ClassicWindow.Styles>
1414
<Style Selector="HeaderedContentControl">
15-
<Setter Property="Padding" Value="3,7,7,4" />
15+
<Setter Property="Padding" Value="11,15,15,12" />
1616
</Style>
1717
<Style Selector="TextBlock">
1818
<Setter Property="VerticalAlignment" Value="Center" />

src/Classic.Avalonia.Theme/Converters/BorderGapMaskConverter.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ internal class BorderGapMaskConverter : IMultiValueConverter
2121

2222
if (parameter == null ||
2323
values == null ||
24-
values.Count != 3 ||
24+
values.Count != 4 ||
2525
values[0] == null ||
2626
values[1] == null ||
2727
values[2] == null ||
28+
values[3] == null ||
2829
!doubleType.IsInstanceOfType(values[0]) ||
2930
!doubleType.IsInstanceOfType(values[1]) ||
30-
!doubleType.IsInstanceOfType(values[2]) )
31+
!doubleType.IsInstanceOfType(values[2]) ||
32+
!doubleType.IsInstanceOfType(values[3]) )
3133
{
3234
return AvaloniaProperty.UnsetValue;
3335
}
@@ -43,8 +45,9 @@ internal class BorderGapMaskConverter : IMultiValueConverter
4345
//
4446

4547
double headerWidth = (double?)values[0] ?? 0;
46-
double borderWidth = (double?)values[1] ?? 0;
47-
double borderHeight = (double?)values[2] ?? 0;
48+
double headerHeight = (double?)values[1] ?? 0;
49+
double borderWidth = (double?)values[2] ?? 0;
50+
double borderHeight = (double?)values[3] ?? 0;
4851

4952
// Doesn't make sense to have a Grid
5053
// with 0 as width or height
@@ -80,7 +83,7 @@ internal class BorderGapMaskConverter : IMultiValueConverter
8083
grid.ColumnDefinitions.Add(colDef3);
8184
RowDefinition rowDef1 = new RowDefinition();
8285
RowDefinition rowDef2 = new RowDefinition();
83-
rowDef1.Height = new GridLength(borderHeight / 2);
86+
rowDef1.Height = new GridLength(Math.Max(0, headerHeight - lineWidth));
8487
rowDef2.Height = new GridLength(1, GridUnitType.Star);
8588
grid.RowDefinitions.Add(rowDef1);
8689
grid.RowDefinitions.Add(rowDef2);

src/Classic.Avalonia.Theme/Styles/HeaderedContentControl.axaml

Lines changed: 74 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -2,99 +2,81 @@
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33
xmlns:theme="clr-namespace:Classic.Avalonia.Theme"
44
xmlns:converters="clr-namespace:Classic.Avalonia.Theme.Converters"
5-
xmlns:common="clr-namespace:Classic.CommonControls;assembly=Classic.CommonControls.Avalonia"
65
x:ClassModifier="internal">
7-
<converters:BorderGapMaskConverter x:Key="BorderGapMaskConverter"/>
8-
<ControlTheme x:Key="{x:Type HeaderedContentControl}"
9-
TargetType="HeaderedContentControl">
10-
<Setter Property="BorderBrush"
11-
Value="{x:Static theme:ClassicBorderDecorator.ClassicBorderBrush}"/>
12-
<Setter Property="BorderThickness"
13-
Value="2"/>
14-
<Setter Property="Template">
15-
<ControlTemplate>
16-
<Grid>
17-
<Grid.ColumnDefinitions>
18-
<ColumnDefinition Width="6"/>
19-
<ColumnDefinition Width="Auto"/>
20-
<ColumnDefinition Width="*"/>
21-
<ColumnDefinition Width="6"/>
22-
</Grid.ColumnDefinitions>
23-
<Grid.RowDefinitions>
24-
<RowDefinition Height="Auto"/>
25-
<RowDefinition Height="Auto"/>
26-
<RowDefinition Height="*"/>
27-
<RowDefinition Height="6"/>
28-
</Grid.RowDefinitions>
29-
<!-- Border for the background with the same CornerRadius as the Border with the Header
30-
Using this because if the background is set in the Border with the Header the opacity
31-
mask will be applied to the background as well. -->
32-
<Border Grid.Row="1"
33-
Grid.RowSpan="3"
34-
Grid.Column="0"
35-
Grid.ColumnSpan="4"
36-
BorderThickness="{TemplateBinding BorderThickness}"
37-
BorderBrush="Transparent"
38-
Background="{TemplateBinding Background}"/>
6+
<Design.PreviewWith>
7+
<HeaderedContentControl Header="Header of the control" Margin="10">
8+
<Border Width="200" Height="200" Background="Red" />
9+
</HeaderedContentControl>
10+
</Design.PreviewWith>
11+
<converters:BorderGapMaskConverter x:Key="BorderGapMaskConverter" />
12+
<ControlTheme x:Key="{x:Type HeaderedContentControl}"
13+
TargetType="HeaderedContentControl">
14+
<Setter Property="BorderBrush"
15+
Value="{x:Static theme:ClassicBorderDecorator.ClassicBorderBrush}" />
16+
<Setter Property="BorderThickness"
17+
Value="2" />
18+
<Setter Property="Padding"
19+
Value="8" />
20+
<Setter Property="ClipToBounds"
21+
Value="True" />
22+
<Setter Property="Template">
23+
<ControlTemplate>
24+
<Panel Background="{TemplateBinding Background}">
25+
<Panel
26+
Margin="0,7,0,0"
27+
ClipToBounds="{TemplateBinding ClipToBounds}">
28+
<ContentPresenter Name="PART_ContentPresenter"
29+
Margin="{TemplateBinding Padding}"
30+
ClipToBounds="{TemplateBinding ClipToBounds}"
31+
ContentTemplate="{TemplateBinding ContentTemplate}"
32+
Content="{TemplateBinding Content}"
33+
RecognizesAccessKey="True"
34+
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
35+
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
36+
FontSize="{TemplateBinding FontSize}"
37+
FontWeight="{TemplateBinding FontWeight}"
38+
FontFamily="{TemplateBinding FontFamily}"
39+
FontStyle="{TemplateBinding FontStyle}" />
40+
</Panel>
3941

40-
<theme:ClassicBorderDecorator Grid.Row="1"
41-
Grid.RowSpan="3"
42-
Grid.ColumnSpan="4"
43-
x:Name="Border"
44-
BorderThickness="{TemplateBinding BorderThickness}"
45-
BorderBrush="{TemplateBinding BorderBrush}"
46-
BorderStyle="Etched">
47-
<!-- https://github.com/AvaloniaUI/Avalonia/issues/11388 -->
48-
<!-- can't use VisualBrush for the OpacityMask, so a workaround - header content presenter has background set, but in general this is not correct -->
49-
<!-- <theme:ClassicBorderDecorator.OpacityMask> -->
50-
<!-- <MultiBinding Converter="{StaticResource BorderGapMaskConverter}" -->
51-
<!-- ConverterParameter="7"> -->
52-
<!-- <Binding ElementName="Header" -->
53-
<!-- Path="Bounds.Width"/> -->
54-
<!-- <Binding ElementName="Border" -->
55-
<!-- Path="Bounds.Width"/> -->
56-
<!-- <Binding ElementName="Border" -->
57-
<!-- Path="Bounds.Height"/> -->
58-
<!-- </MultiBinding> -->
59-
<!-- </theme:ClassicBorderDecorator.OpacityMask> -->
60-
</theme:ClassicBorderDecorator>
6142

62-
<!-- ContentPresenter for the header -->
63-
<Border x:Name="Header"
64-
Padding="3,0,3,0"
65-
Grid.Row="0"
66-
Grid.RowSpan="2"
67-
Grid.Column="1">
68-
<ContentPresenter Name="PART_HeaderPresenter"
69-
Content="{TemplateBinding Header}"
70-
RecognizesAccessKey="True"
71-
ContentTemplate="{TemplateBinding HeaderTemplate}"
72-
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
73-
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
74-
FontSize="{TemplateBinding FontSize}"
75-
FontWeight="{TemplateBinding FontWeight}"
76-
FontFamily="{TemplateBinding FontFamily}"
77-
FontStyle="{TemplateBinding FontStyle}"
78-
Background="{DynamicResource {x:Static common:SystemColors.ControlBrushKey}}" /> <!-- workaround for OpacityMask -->
43+
<theme:ClassicBorderDecorator x:Name="Border"
44+
Margin="0,7,0,0"
45+
BorderThickness="{TemplateBinding BorderThickness}"
46+
BorderBrush="{TemplateBinding BorderBrush}"
47+
BorderStyle="Etched">
7948

80-
</Border>
81-
<!-- Primary content for GroupBox -->
82-
<ContentPresenter Name="PART_ContentPresenter"
83-
Grid.Row="2"
84-
Grid.Column="1"
85-
Grid.ColumnSpan="2"
86-
Margin="{TemplateBinding Padding}"
87-
ContentTemplate="{TemplateBinding ContentTemplate}"
88-
Content="{TemplateBinding Content}"
89-
RecognizesAccessKey="True"
90-
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
91-
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
92-
FontSize="{TemplateBinding FontSize}"
93-
FontWeight="{TemplateBinding FontWeight}"
94-
FontFamily="{TemplateBinding FontFamily}"
95-
FontStyle="{TemplateBinding FontStyle}"/>
96-
</Grid>
97-
</ControlTemplate>
98-
</Setter>
99-
</ControlTheme>
100-
</ResourceDictionary>
49+
<theme:ClassicBorderDecorator.OpacityMask>
50+
<MultiBinding Converter="{StaticResource BorderGapMaskConverter}"
51+
ConverterParameter="7">
52+
<Binding ElementName="Header"
53+
Path="Bounds.Width" />
54+
<Binding ElementName="Header"
55+
Path="Bounds.Height" />
56+
<Binding ElementName="Border"
57+
Path="Bounds.Width" />
58+
<Binding ElementName="Border"
59+
Path="Bounds.Height" />
60+
</MultiBinding>
61+
</theme:ClassicBorderDecorator.OpacityMask>
62+
</theme:ClassicBorderDecorator>
63+
64+
<Border x:Name="Header"
65+
Margin="5,0,0,0"
66+
Padding="3,0,3,0"
67+
HorizontalAlignment="Left"
68+
VerticalAlignment="Top">
69+
<ContentPresenter Name="PART_HeaderPresenter"
70+
Content="{TemplateBinding Header}"
71+
RecognizesAccessKey="True"
72+
ContentTemplate="{TemplateBinding HeaderTemplate}"
73+
FontSize="{TemplateBinding FontSize}"
74+
FontWeight="{TemplateBinding FontWeight}"
75+
FontFamily="{TemplateBinding FontFamily}"
76+
FontStyle="{TemplateBinding FontStyle}" />
77+
</Border>
78+
</Panel>
79+
</ControlTemplate>
80+
</Setter>
81+
</ControlTheme>
82+
</ResourceDictionary>

0 commit comments

Comments
 (0)