diff --git a/Settings.XamlStyler b/Settings.XamlStyler
index 117aea82adf0..d831092fff19 100644
--- a/Settings.XamlStyler
+++ b/Settings.XamlStyler
@@ -1,3 +1,4 @@
{
- "IndentWithTabs": true
+ "IndentWithTabs": true,
+ "NoNewLineMarkupExtensions": "x:Bind, Binding, controls:ThemedIconMarkup",
}
\ No newline at end of file
diff --git a/src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.cs b/src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.cs
index b43b0ab454c1..500fee8a96a0 100644
--- a/src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.cs
+++ b/src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.cs
@@ -42,7 +42,7 @@ public BreadcrumbBar()
{
DefaultStyleKey = typeof(BreadcrumbBar);
- _itemsRepeaterLayout = new(this, 2d);
+ _itemsRepeaterLayout = new(this);
}
// Methods
@@ -87,12 +87,13 @@ internal protected virtual void RaiseItemDropDownFlyoutClosed(BreadcrumbBarItem
internal protected virtual void OnLayoutUpdated()
{
- if (_itemsRepeater is null)
+ if (_itemsRepeater is null || (_itemsRepeaterLayout.IndexAfterEllipsis > _itemsRepeaterLayout.VisibleItemsCount && _isEllipsisRendered))
return;
+ if (_ellipsisBreadcrumbBarItem is not null && _isEllipsisRendered != _itemsRepeaterLayout.EllipsisIsRendered)
+ _ellipsisBreadcrumbBarItem.Visibility = _itemsRepeaterLayout.EllipsisIsRendered ? Visibility.Visible : Visibility.Collapsed;
+
_isEllipsisRendered = _itemsRepeaterLayout.EllipsisIsRendered;
- if (_ellipsisBreadcrumbBarItem is not null)
- _ellipsisBreadcrumbBarItem.Visibility = _isEllipsisRendered ? Visibility.Visible : Visibility.Collapsed;
for (int accessibilityIndex = 0, collectionIndex = _itemsRepeaterLayout.IndexAfterEllipsis;
accessibilityIndex < _itemsRepeaterLayout.VisibleItemsCount;
diff --git a/src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.xaml b/src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.xaml
index 5f92aed85ec2..213ab4cd8340 100644
--- a/src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.xaml
+++ b/src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.xaml
@@ -5,13 +5,14 @@
xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
xmlns:local="using:Files.App.Controls">
- 32
+ 34
120
16
4,0
8,0
16,0,8,0
+ 2,0,0,0
2,2,2,2
2,2,2,2
@@ -21,21 +22,33 @@
+
+
+
+
+
+
-
-
diff --git a/src/Files.App.Controls/Omnibar/OmnibarModeSeparator.cs b/src/Files.App.Controls/Omnibar/OmnibarModeSeparator.cs
new file mode 100644
index 000000000000..2eaf6fbed8ae
--- /dev/null
+++ b/src/Files.App.Controls/Omnibar/OmnibarModeSeparator.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Files Community
+// Licensed under the MIT License.
+
+namespace Files.App.Controls
+{
+ public partial class OmnibarModeSeparator : Control
+ {
+ // Constructor
+
+ public OmnibarModeSeparator()
+ {
+ DefaultStyleKey = typeof(OmnibarMode);
+ }
+
+ // Methods
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+ }
+ }
+}
diff --git a/src/Files.App.Controls/Omnibar/OmnibarTextChangeReason.cs b/src/Files.App.Controls/Omnibar/OmnibarTextChangeReason.cs
new file mode 100644
index 000000000000..8a4c41e2b3be
--- /dev/null
+++ b/src/Files.App.Controls/Omnibar/OmnibarTextChangeReason.cs
@@ -0,0 +1,16 @@
+// Copyright (c) Files Community
+// Licensed under the MIT License.
+
+namespace Files.App.Controls
+{
+ public enum OmnibarTextChangeReason
+ {
+ UserInput,
+
+ SuggestionChosen,
+
+ ProgrammaticChange,
+
+ None,
+ }
+}
diff --git a/src/Files.App.Controls/ThemedIcon/ThemedIconMarkup.cs b/src/Files.App.Controls/ThemedIcon/ThemedIconMarkup.cs
new file mode 100644
index 000000000000..23bd9a1342e7
--- /dev/null
+++ b/src/Files.App.Controls/ThemedIcon/ThemedIconMarkup.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Files Community
+// Licensed under the MIT License.
+
+using Microsoft.UI.Xaml.Markup;
+
+namespace Files.App.Controls
+{
+ [MarkupExtensionReturnType(ReturnType = typeof(ThemedIcon))]
+ public sealed partial class ThemedIconMarkup : MarkupExtension
+ {
+ public Style Style { get; set; } = null!;
+
+ public bool IsFilled { get; set; }
+
+ public ThemedIconTypes IconType { get; set; }
+
+ protected override object ProvideValue()
+ {
+ return new ThemedIcon() { Style = Style, IsFilled = IsFilled, IconType = IconType };
+ }
+ }
+}
diff --git a/src/Files.App.Controls/Themes/Generic.xaml b/src/Files.App.Controls/Themes/Generic.xaml
index 4e66b0e77870..910ef94ce52b 100644
--- a/src/Files.App.Controls/Themes/Generic.xaml
+++ b/src/Files.App.Controls/Themes/Generic.xaml
@@ -60,7 +60,6 @@
-
diff --git a/tests/Files.App.UITests/Data/DummyItem2.cs b/tests/Files.App.UITests/Data/BreadcrumbBarItemModel.cs
similarity index 55%
rename from tests/Files.App.UITests/Data/DummyItem2.cs
rename to tests/Files.App.UITests/Data/BreadcrumbBarItemModel.cs
index 048ee1fa236e..9d6169ab1d69 100644
--- a/tests/Files.App.UITests/Data/DummyItem2.cs
+++ b/tests/Files.App.UITests/Data/BreadcrumbBarItemModel.cs
@@ -5,5 +5,5 @@
namespace Files.App.UITests.Data
{
- internal record DummyItem2(string Text, ObservableCollection? Children = null);
+ internal record BreadcrumbBarItemModel(string Text, ObservableCollection? Children = null);
}
diff --git a/tests/Files.App.UITests/Data/DummyItem1.cs b/tests/Files.App.UITests/Data/DummyItem1.cs
deleted file mode 100644
index b7cbcc219245..000000000000
--- a/tests/Files.App.UITests/Data/DummyItem1.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) Files Community
-// Licensed under the MIT License.
-
-namespace Files.App.UITests.Data
-{
- internal record DummyItem1(string Title, string Description, string HotKeys);
-}
diff --git a/tests/Files.App.UITests/Data/OmnibarPaletteSuggestionItem.cs b/tests/Files.App.UITests/Data/OmnibarPaletteSuggestionItem.cs
new file mode 100644
index 000000000000..db6d31d2519d
--- /dev/null
+++ b/tests/Files.App.UITests/Data/OmnibarPaletteSuggestionItem.cs
@@ -0,0 +1,24 @@
+// Copyright (c) Files Community
+// Licensed under the MIT License.
+
+using Files.App.Controls;
+using System;
+
+namespace Files.App.UITests.Data
+{
+ public partial record OmnibarPaletteSuggestionItem(string Title, string Description, string HotKeys)
+ : IOmnibarTextMemberPathProvider
+ {
+ ///
+ public string GetTextMemberPath(string textMemberPath)
+ {
+ return textMemberPath switch
+ {
+ nameof(Title) => Title,
+ nameof(Description) => Description,
+ nameof(HotKeys) => HotKeys,
+ _ => throw new ArgumentOutOfRangeException(nameof(textMemberPath), textMemberPath, null),
+ };
+ }
+ }
+}
diff --git a/tests/Files.App.UITests/Views/BreadcrumbBarPage.xaml b/tests/Files.App.UITests/Views/BreadcrumbBarPage.xaml
index 2044818bbef3..bcff33b8e32f 100644
--- a/tests/Files.App.UITests/Views/BreadcrumbBarPage.xaml
+++ b/tests/Files.App.UITests/Views/BreadcrumbBarPage.xaml
@@ -15,7 +15,7 @@
-
-
-
-
+
+
diff --git a/tests/Files.App.UITests/Views/BreadcrumbBarPage.xaml.cs b/tests/Files.App.UITests/Views/BreadcrumbBarPage.xaml.cs
index 32b5cd27c0c1..8b3deb1cc97e 100644
--- a/tests/Files.App.UITests/Views/BreadcrumbBarPage.xaml.cs
+++ b/tests/Files.App.UITests/Views/BreadcrumbBarPage.xaml.cs
@@ -12,7 +12,7 @@ namespace Files.App.UITests.Views
{
public sealed partial class BreadcrumbBarPage : Page
{
- private readonly ObservableCollection DummyItems;
+ private readonly ObservableCollection DummyItems;
[GeneratedDependencyProperty]
private partial string? ClickedItemName { get; set; }
diff --git a/tests/Files.App.UITests/Views/OmnibarPage.xaml b/tests/Files.App.UITests/Views/OmnibarPage.xaml
index 43ddf95bbc20..26a4a1604835 100644
--- a/tests/Files.App.UITests/Views/OmnibarPage.xaml
+++ b/tests/Files.App.UITests/Views/OmnibarPage.xaml
@@ -14,189 +14,133 @@
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
-
+
+
-
+
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
-
diff --git a/tests/Files.App.UITests/Views/OmnibarPage.xaml.cs b/tests/Files.App.UITests/Views/OmnibarPage.xaml.cs
index a1d577b09b69..0fd9bc89e01e 100644
--- a/tests/Files.App.UITests/Views/OmnibarPage.xaml.cs
+++ b/tests/Files.App.UITests/Views/OmnibarPage.xaml.cs
@@ -1,6 +1,8 @@
// Copyright (c) Files Community
// Licensed under the MIT License.
+using CommunityToolkit.WinUI;
+using Files.App.Controls;
using Files.App.UITests.Data;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
@@ -10,13 +12,28 @@ namespace Files.App.UITests.Views
{
public sealed partial class OmnibarPage : Page
{
- private readonly ObservableCollection DummyItems1;
+ private readonly string Omnibar1_TextMemberPathForPaletteMode = nameof(OmnibarPaletteSuggestionItem.Title);
+
+ private readonly ObservableCollection Omnibar1_PaletteSuggestions;
+ private readonly ObservableCollection Omnibar1_BreadcrumbBarItems;
+
+ [GeneratedDependencyProperty(DefaultValue = "")]
+ private partial string Omnibar1_Text { get; set; }
+
+ [GeneratedDependencyProperty(DefaultValue = "")]
+ private partial string Omnibar1_TextChangedReason { get; set; }
+
+ [GeneratedDependencyProperty]
+ private partial int Omnibar1_ChosenSuggestionIndex { get; set; }
+
+ [GeneratedDependencyProperty(DefaultValue = "")]
+ private partial string Omnibar1_SubmittedQuery { get; set; }
public OmnibarPage()
{
InitializeComponent();
- DummyItems1 =
+ Omnibar1_PaletteSuggestions =
[
new("Open online help page in browser", "Open online help page in browser", "Control + H"),
new("Toggle full screen", "Toggle full screen", "Control + H"),
@@ -28,6 +45,50 @@ public OmnibarPage()
new("Undo the last file operation", "Undo the last file operation", "Control + H"),
new("Toggle whether to show hidden items", "Toggle whether to show hidden items", "Control + H"),
];
+
+ Omnibar1_BreadcrumbBarItems =
+ [
+ new("Local Disk (C:)"),
+ new("Users"),
+ new("me"),
+ new("OneDrive"),
+ new("Desktop"),
+ new("Folder1"),
+ new("Folder2"),
+ ];
+ }
+
+ private void Omnibar1_BreadcrumbBar_ItemDropDownFlyoutOpening(object sender, BreadcrumbBarItemDropDownFlyoutEventArgs e)
+ {
+ e.Flyout.Items.Add(new MenuFlyoutItem { Icon = new FontIcon() { Glyph = "\uE8B7" }, Text = "Item 1" });
+ e.Flyout.Items.Add(new MenuFlyoutItem { Icon = new FontIcon() { Glyph = "\uE8B7" }, Text = "Item 2" });
+ e.Flyout.Items.Add(new MenuFlyoutItem { Icon = new FontIcon() { Glyph = "\uE8B7" }, Text = "Item 3" });
+ }
+
+ private void Omnibar1_BreadcrumbBar_ItemDropDownFlyoutClosed(object sender, BreadcrumbBarItemDropDownFlyoutEventArgs e)
+ {
+ e.Flyout.Items.Clear();
+ }
+
+ private void Omnibar1_QuerySubmitted(Omnibar sender, OmnibarQuerySubmittedEventArgs args)
+ {
+ Omnibar1_ChosenSuggestionIndex = args.Item is OmnibarPaletteSuggestionItem item ? Omnibar1_PaletteSuggestions.IndexOf(item) : -1;
+ Omnibar1_SubmittedQuery = args.Mode.Text ?? string.Empty;
+ }
+
+ private void Omnibar1_TextChanged(Omnibar sender, OmnibarTextChangedEventArgs args)
+ {
+ if (args.Reason is not OmnibarTextChangeReason.SuggestionChosen)
+ Omnibar1_ChosenSuggestionIndex = -1;
+
+ Omnibar1_Text = args.Mode.Text ?? string.Empty;
+ Omnibar1_TextChangedReason = args.Reason.ToString();
+ }
+
+ private void Omnibar1_SuggestionChosen(Omnibar sender, OmnibarSuggestionChosenEventArgs args)
+ {
+ Omnibar1_ChosenSuggestionIndex = args.SelectedItem is OmnibarPaletteSuggestionItem item ? Omnibar1_PaletteSuggestions.IndexOf(item) : -1;
+ Omnibar1_SubmittedQuery = args.Mode.Text ?? string.Empty;
}
}
}