Skip to content

Commit 19c6f1e

Browse files
authored
Code Quality: Brushed up Omnibar and BreadcrumbBar (#16973)
1 parent f4680b5 commit 19c6f1e

27 files changed

+1146
-605
lines changed

Settings.XamlStyler

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"IndentWithTabs": true
2+
"IndentWithTabs": true,
3+
"NoNewLineMarkupExtensions": "x:Bind, Binding, controls:ThemedIconMarkup",
34
}

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public BreadcrumbBar()
4242
{
4343
DefaultStyleKey = typeof(BreadcrumbBar);
4444

45-
_itemsRepeaterLayout = new(this, 2d);
45+
_itemsRepeaterLayout = new(this);
4646
}
4747

4848
// Methods
@@ -87,12 +87,13 @@ internal protected virtual void RaiseItemDropDownFlyoutClosed(BreadcrumbBarItem
8787

8888
internal protected virtual void OnLayoutUpdated()
8989
{
90-
if (_itemsRepeater is null)
90+
if (_itemsRepeater is null || (_itemsRepeaterLayout.IndexAfterEllipsis > _itemsRepeaterLayout.VisibleItemsCount && _isEllipsisRendered))
9191
return;
9292

93+
if (_ellipsisBreadcrumbBarItem is not null && _isEllipsisRendered != _itemsRepeaterLayout.EllipsisIsRendered)
94+
_ellipsisBreadcrumbBarItem.Visibility = _itemsRepeaterLayout.EllipsisIsRendered ? Visibility.Visible : Visibility.Collapsed;
95+
9396
_isEllipsisRendered = _itemsRepeaterLayout.EllipsisIsRendered;
94-
if (_ellipsisBreadcrumbBarItem is not null)
95-
_ellipsisBreadcrumbBarItem.Visibility = _isEllipsisRendered ? Visibility.Visible : Visibility.Collapsed;
9697

9798
for (int accessibilityIndex = 0, collectionIndex = _itemsRepeaterLayout.IndexAfterEllipsis;
9899
accessibilityIndex < _itemsRepeaterLayout.VisibleItemsCount;

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.xaml

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
66
xmlns:local="using:Files.App.Controls">
77

8-
<x:Double x:Key="BreadcrumbBarHeight">32</x:Double>
8+
<x:Double x:Key="BreadcrumbBarHeight">34</x:Double>
99
<x:Double x:Key="BreadcrumbBarMinWidth">120</x:Double>
1010
<x:Double x:Key="BreadcrumbBarEllipsisFontSize">16</x:Double>
1111

1212
<Thickness x:Key="BreadcrumbBarChevronPadding">4,0</Thickness>
1313
<Thickness x:Key="BreadcrumbBarItemPadding">8,0</Thickness>
1414
<Thickness x:Key="BreadcrumbBarRootItemPadding">16,0,8,0</Thickness>
15+
<Thickness x:Key="BreadcrumbBarItemMargin">2,0,0,0</Thickness>
1516

1617
<CornerRadius x:Key="BreadcrumbBarItemCornerRadius">2,2,2,2</CornerRadius>
1718
<CornerRadius x:Key="BreadcrumbBarChevronCornerRaduis">2,2,2,2</CornerRadius>
@@ -21,21 +22,33 @@
2122
<Style BasedOn="{StaticResource DefaultBreadcrumbBarItemStyle}" TargetType="local:BreadcrumbBarItem" />
2223

2324
<Style x:Key="DefaultBreadcrumbBarStyle" TargetType="local:BreadcrumbBar">
25+
2426
<Setter Property="MinWidth" Value="{StaticResource BreadcrumbBarMinWidth}" />
27+
28+
<Setter Property="HorizontalAlignment" Value="Stretch" />
29+
<Setter Property="HorizontalContentAlignment" Value="Center" />
30+
<Setter Property="VerticalAlignment" Value="Stretch" />
31+
<Setter Property="VerticalContentAlignment" Value="Center" />
32+
2533
<Setter Property="AutomationProperties.LandmarkType" Value="Navigation" />
34+
2635
<Setter Property="IsTabStop" Value="False" />
36+
2737
<Setter Property="Template">
2838
<Setter.Value>
2939
<ControlTemplate TargetType="local:BreadcrumbBar">
3040
<Grid
3141
MinWidth="{TemplateBinding MinWidth}"
32-
ColumnSpacing="2"
42+
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
43+
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
44+
Background="{TemplateBinding Background}"
3345
TabFocusNavigation="Once"
3446
XYFocusKeyboardNavigation="Enabled">
3547
<Grid.ColumnDefinitions>
3648
<ColumnDefinition Width="Auto" />
3749
<ColumnDefinition Width="Auto" />
3850
<ColumnDefinition Width="*" />
51+
<ColumnDefinition Width="Auto" />
3952
</Grid.ColumnDefinitions>
4053

4154
<local:BreadcrumbBarItem
@@ -50,6 +63,7 @@
5063
<local:BreadcrumbBarItem
5164
x:Name="PART_EllipsisBreadcrumbBarItem"
5265
Grid.Column="1"
66+
Margin="{StaticResource BreadcrumbBarItemMargin}"
5367
AutomationProperties.AccessibilityView="Content"
5468
IsEllipsis="True"
5569
Visibility="Collapsed">
@@ -59,6 +73,8 @@
5973
<ItemsRepeater
6074
x:Name="PART_MainItemsRepeater"
6175
Grid.Column="2"
76+
Margin="{StaticResource BreadcrumbBarItemMargin}"
77+
HorizontalAlignment="Left"
6278
ItemTemplate="{Binding ItemTemplate, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
6379
ItemsSource="{Binding ItemsSource, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" />
6480

@@ -85,17 +101,17 @@
85101
<Setter Property="HorizontalAlignment" Value="Stretch" />
86102
<Setter Property="HorizontalContentAlignment" Value="Center" />
87103
<Setter Property="VerticalAlignment" Value="Stretch" />
88-
<Setter Property="VerticalContentAlignment" Value="Center" />
104+
<Setter Property="VerticalContentAlignment" Value="Stretch" />
89105

90106
<Setter Property="FocusVisualMargin" Value="1" />
91107
<Setter Property="IsTabStop" Value="False" />
92108
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
109+
93110
<Setter Property="Template">
94111
<Setter.Value>
95112
<ControlTemplate TargetType="local:BreadcrumbBarItem">
96113
<Grid
97114
x:Name="PART_LayoutRoot"
98-
ColumnSpacing="2"
99115
TabFocusNavigation="Once"
100116
XYFocusKeyboardNavigation="Enabled">
101117
<Grid.ColumnDefinitions>
@@ -107,14 +123,21 @@
107123
<Button
108124
x:Name="PART_ItemContentButton"
109125
Padding="{TemplateBinding Padding}"
110-
VerticalAlignment="Stretch"
126+
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
111127
AutomationProperties.AccessibilityView="Raw"
112128
Background="{TemplateBinding Background}"
113129
BorderBrush="{TemplateBinding BorderBrush}"
114130
BorderThickness="{TemplateBinding BorderThickness}"
115131
Control.IsTemplateFocusTarget="True"
116132
CornerRadius="{TemplateBinding CornerRadius}"
117133
UseSystemFocusVisuals="True">
134+
<Button.Resources>
135+
<ResourceDictionary>
136+
<StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="SubtleFillColorTertiaryBrush" />
137+
<StaticResource x:Key="ButtonBackgroundPressed" ResourceKey="SubtleFillColorSecondaryBrush" />
138+
</ResourceDictionary>
139+
</Button.Resources>
140+
118141
<FlyoutBase.AttachedFlyout>
119142
<MenuFlyout
120143
x:Name="PART_ItemEllipsisDropDownMenuFlyout"
@@ -151,15 +174,23 @@
151174
<Button
152175
x:Name="PART_ItemChevronButton"
153176
Grid.Column="1"
177+
Margin="{StaticResource BreadcrumbBarItemMargin}"
154178
Padding="{StaticResource BreadcrumbBarChevronPadding}"
155-
VerticalAlignment="Stretch"
179+
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
156180
AutomationProperties.AccessibilityView="Content"
157181
Background="{TemplateBinding Background}"
158182
BorderBrush="{TemplateBinding BorderBrush}"
159183
BorderThickness="{TemplateBinding BorderThickness}"
160184
CornerRadius="{StaticResource BreadcrumbBarChevronCornerRaduis}"
161185
Style="{StaticResource BreadcrumbBarItemChevronButtonStyle}"
162186
UseSystemFocusVisuals="True">
187+
<Button.Resources>
188+
<ResourceDictionary>
189+
<StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="SubtleFillColorTertiaryBrush" />
190+
<StaticResource x:Key="ButtonBackgroundPressed" ResourceKey="SubtleFillColorSecondaryBrush" />
191+
</ResourceDictionary>
192+
</Button.Resources>
193+
163194
<FlyoutBase.AttachedFlyout>
164195
<MenuFlyout
165196
x:Name="PART_ItemChevronDropDownMenuFlyout"

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarItem.cs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,31 +55,33 @@ protected override void OnApplyTemplate()
5555

5656
public void OnItemClicked()
5757
{
58-
if (_ownerRef is not null &&
59-
_ownerRef.TryGetTarget(out var breadcrumbBar))
58+
if (_ownerRef is null ||
59+
!_ownerRef.TryGetTarget(out var breadcrumbBar))
60+
return;
61+
62+
if (IsEllipsis)
6063
{
61-
if (IsEllipsis)
62-
{
63-
// Clear items in the ellipsis flyout
64-
_itemEllipsisDropDownMenuFlyout.Items.Clear();
64+
// Clear items in the ellipsis flyout
65+
_itemEllipsisDropDownMenuFlyout.Items.Clear();
6566

66-
// Populate items in the ellipsis flyout
67-
for (int index = 0; index < breadcrumbBar.IndexAfterEllipsis; index++)
67+
// Populate items in the ellipsis flyout
68+
for (int index = 0; index < breadcrumbBar.IndexAfterEllipsis; index++)
69+
{
70+
if (breadcrumbBar.TryGetElement(index, out var item) && item?.Content is string text)
6871
{
69-
if (breadcrumbBar.TryGetElement(index, out var item) && item?.Content is string text)
70-
{
71-
_itemEllipsisDropDownMenuFlyout.Items.Add(new MenuFlyoutItem() { Text = text });
72-
}
72+
var menuFlyoutItem = new MenuFlyoutItem() { Text = text };
73+
_itemEllipsisDropDownMenuFlyout.Items.Add(menuFlyoutItem);
74+
menuFlyoutItem.Click += (sender, e) => breadcrumbBar.RaiseItemClickedEvent(item);
7375
}
74-
75-
// Open the ellipsis flyout
76-
FlyoutBase.ShowAttachedFlyout(_itemContentButton);
77-
}
78-
else
79-
{
80-
// Fire a click event
81-
breadcrumbBar.RaiseItemClickedEvent(this);
8276
}
77+
78+
// Open the ellipsis flyout
79+
FlyoutBase.ShowAttachedFlyout(_itemContentButton);
80+
}
81+
else
82+
{
83+
// Fire a click event
84+
breadcrumbBar.RaiseItemClickedEvent(this);
8385
}
8486
}
8587

src/Files.App.Controls/BreadcrumbBar/BreadcrumbBarLayout.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ public partial class BreadcrumbBarLayout : NonVirtualizingLayout
1313
// Fields
1414

1515
private readonly WeakReference<BreadcrumbBar>? _ownerRef;
16-
private readonly double _spacing = 0d;
1716

1817
private Size _availableSize;
1918
private BreadcrumbBarItem? _ellipsisButton = null;
@@ -24,10 +23,9 @@ public partial class BreadcrumbBarLayout : NonVirtualizingLayout
2423
public int IndexAfterEllipsis { get; private set; }
2524
public int VisibleItemsCount { get; private set; }
2625

27-
public BreadcrumbBarLayout(BreadcrumbBar breadcrumb, double spacing)
26+
public BreadcrumbBarLayout(BreadcrumbBar breadcrumb)
2827
{
2928
_ownerRef = new(breadcrumb);
30-
_spacing = spacing;
3129
}
3230

3331
protected override Size MeasureOverride(NonVirtualizingLayoutContext context, Size availableSize)
@@ -79,7 +77,6 @@ protected override Size ArrangeOverride(NonVirtualizingLayoutContext context, Si
7977
breadcrumbItem.Arrange(new Rect(accumulatedWidths, 0, breadcrumbItem.DesiredSize.Width, breadcrumbItem.DesiredSize.Height));
8078

8179
accumulatedWidths += breadcrumbItem.DesiredSize.Width;
82-
accumulatedWidths += _spacing;
8380

8481
VisibleItemsCount++;
8582
}
@@ -89,15 +86,17 @@ protected override Size ArrangeOverride(NonVirtualizingLayoutContext context, Si
8986
if (_ownerRef?.TryGetTarget(out var breadcrumbBar) ?? false)
9087
breadcrumbBar.OnLayoutUpdated();
9188

89+
finalSize.Width = accumulatedWidths;
90+
9291
return finalSize;
9392
}
9493

9594
private int GetFirstIndexToRender(NonVirtualizingLayoutContext context)
9695
{
9796
var itemCount = context.Children.Count;
98-
var accumulatedWidth = _spacing;
97+
var accumulatedWidth = 0d;
9998

100-
// Go through all items from the end
99+
// Go through all items from the last item
101100
for (int index = itemCount - 1; index >= 0; index--)
102101
{
103102
var newAccumulatedWidth = accumulatedWidth + context.Children[index].DesiredSize.Width;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
namespace Files.App.Controls
5+
{
6+
public record class OmnibarQuerySubmittedEventArgs(OmnibarMode Mode, object? Item, string Text);
7+
8+
public record class OmnibarSuggestionChosenEventArgs(OmnibarMode Mode, object SelectedItem);
9+
10+
public record class OmnibarTextChangedEventArgs(OmnibarMode Mode, OmnibarTextChangeReason Reason);
11+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
namespace Files.App.Controls
5+
{
6+
/// <summary>
7+
/// An interface that provides a way to get the text member path of <see cref="OmnibarMode.SuggestionItemsSource"/>.
8+
/// </summary>
9+
/// <remarks>
10+
/// An alternative to this interface is to use an <see cref="Microsoft.UI.Xaml.Data.IBindableCustomPropertyImplementation"/> powered by CsWinRT.
11+
/// </remarks>
12+
public interface IOmnibarTextMemberPathProvider
13+
{
14+
/// <summary>
15+
/// Retrieves the path of the text member as a string. This path can be used to identify the location of the text member.
16+
/// </summary>
17+
/// <returns>Returns a string representing the path of the text member.</returns>
18+
string GetTextMemberPath(string textMemberPath);
19+
}
20+
}

0 commit comments

Comments
 (0)