11// Copyright (c) Files Community
22// Licensed under the MIT License.
33
4+ using CommunityToolkit . WinUI ;
45using Microsoft . UI . Xaml ;
56using Microsoft . UI . Xaml . Controls ;
67using Microsoft . UI . Xaml . Media ;
78using Microsoft . UI . Xaml . Markup ;
89using Microsoft . UI . Xaml . Shapes ;
910using Microsoft . UI . Xaml . Input ;
1011using Microsoft . UI ;
12+ using Windows . ApplicationModel . Contacts ;
1113
1214namespace Files . App . Controls
1315{
@@ -17,12 +19,16 @@ namespace Files.App.Controls
1719 [ TemplatePart ( Name = "PART_ModesHostGrid" , Type = typeof ( Grid ) ) ]
1820 // Visual states
1921 [ TemplateVisualState ( Name = "Focused" , GroupName = "FocusStates" ) ]
20- [ TemplateVisualState ( Name = "Unfocused " , GroupName = "FocusStates" ) ]
22+ [ TemplateVisualState ( Name = "Normal " , GroupName = "FocusStates" ) ]
2123 public partial class Omnibar : Control
2224 {
2325 private const string ModesHostGrid = "PART_ModesHostGrid" ;
26+ private const string AutoSuggestPopup = "PART_AutoSuggestPopup" ;
27+ private const string AutoSuggestBoxBorder = "PART_AutoSuggestBoxBorder" ;
2428
2529 private Grid ? _modesHostGrid ;
30+ private Popup ? _autoSuggestPopup ;
31+ private Border ? _autoSuggestBoxBorder ;
2632 private bool _isFocused ;
2733
2834 public Omnibar ( )
@@ -36,11 +42,19 @@ protected override void OnApplyTemplate()
3642 {
3743 _modesHostGrid = GetTemplateChild ( ModesHostGrid ) as Grid
3844 ?? throw new MissingFieldException ( $ "Could not find { ModesHostGrid } in the given { nameof ( Omnibar ) } 's style.") ;
45+ _autoSuggestPopup = GetTemplateChild ( AutoSuggestPopup ) as Popup
46+ ?? throw new MissingFieldException ( $ "Could not find { AutoSuggestPopup } in the given { nameof ( Omnibar ) } 's style.") ;
47+ _autoSuggestBoxBorder = GetTemplateChild ( AutoSuggestBoxBorder ) as Border
48+ ?? throw new MissingFieldException ( $ "Could not find { AutoSuggestBoxBorder } in the given { nameof ( Omnibar ) } 's style.") ;
3949
4050 if ( Modes is null )
4151 return ;
4252
43- // Populate the modes1
53+ // Add shadow to the popup and set the proper width
54+ _autoSuggestBoxBorder ! . Translation = new ( 0 , 0 , 32 ) ;
55+ _autoSuggestBoxBorder ! . Width = _modesHostGrid ! . ActualWidth ;
56+
57+ // Populate the modes
4458 foreach ( var mode in Modes )
4559 {
4660 // Insert a divider
@@ -63,9 +77,14 @@ protected override void OnApplyTemplate()
6377 _modesHostGrid . ColumnDefinitions . Add ( new ( ) { Width = GridLength . Auto } ) ;
6478 Grid . SetColumn ( mode , _modesHostGrid . Children . Count ) ;
6579 _modesHostGrid . Children . Add ( mode ) ;
66- mode . Host = _modesHostGrid ;
80+ mode . Host = this ;
81+
82+ //if (mode.UseDefaultInactiveMode)
83+ // mode.ContentOnInactive = DefaultInactiveMode;
6784 }
6885
86+ _modesHostGrid . SizeChanged += ModesHostGrid_SizeChanged ;
87+
6988 GotFocus += Omnibar_GotFocus ;
7089 LostFocus += Omnibar_LostFocus ;
7190
@@ -74,18 +93,54 @@ protected override void OnApplyTemplate()
7493 base . OnApplyTemplate ( ) ;
7594 }
7695
77- // Private methods
96+ // Methods
97+
98+ internal void ChangeMode ( OmnibarMode modeToExpand )
99+ {
100+ if ( _modesHostGrid is null || Modes is null )
101+ throw new NullReferenceException ( ) ;
102+
103+ // Reset
104+ foreach ( var column in _modesHostGrid . ColumnDefinitions )
105+ column . Width = GridLength . Auto ;
106+ foreach ( var mode in Modes )
107+ VisualStateManager . GoToState ( mode , "Unfocused" , true ) ;
108+
109+ // Expand the given mode
110+ VisualStateManager . GoToState ( modeToExpand , "Focused" , true ) ;
111+ _modesHostGrid . ColumnDefinitions [ _modesHostGrid . Children . IndexOf ( modeToExpand ) ] . Width = new ( 1 , GridUnitType . Star ) ;
112+
113+ CurrentActiveMode = modeToExpand ;
114+
115+ UpdateVisualStates ( ) ;
116+ }
78117
79118 private void UpdateVisualStates ( )
80119 {
81- VisualStateManager . GoToState (
82- this ,
83- _isFocused ? "Focused" : "Normal" ,
84- true ) ;
120+ VisualStateManager . GoToState ( this , _isFocused ? "Focused" : "Normal" , true ) ;
121+
122+ if ( CurrentActiveMode is not null && _autoSuggestPopup is not null )
123+ {
124+ // Close anyway
125+ if ( _autoSuggestPopup . IsOpen && CurrentActiveMode . SuggestionItemsSource is null )
126+ VisualStateManager . GoToState ( this , "PopupClosed" , true ) ;
127+
128+ // Decide open or close
129+ if ( _isFocused != _autoSuggestPopup . IsOpen )
130+ VisualStateManager . GoToState ( this , _isFocused && CurrentActiveMode . SuggestionItemsSource is not null ? "PopupOpened" : "PopupClosed" , true ) ;
131+ }
132+
133+ if ( CurrentActiveMode is not null )
134+ VisualStateManager . GoToState ( CurrentActiveMode , _isFocused ? "Focused" : "CurrentUnfocused" , true ) ;
85135 }
86136
87137 // Events
88138
139+ private void ModesHostGrid_SizeChanged ( object sender , SizeChangedEventArgs e )
140+ {
141+ _autoSuggestBoxBorder ! . Width = _modesHostGrid ! . ActualWidth ;
142+ }
143+
89144 private void Omnibar_GotFocus ( object sender , RoutedEventArgs e )
90145 {
91146 _isFocused = true ;
@@ -94,6 +149,13 @@ private void Omnibar_GotFocus(object sender, RoutedEventArgs e)
94149
95150 private void Omnibar_LostFocus ( object sender , RoutedEventArgs e )
96151 {
152+ // Ignore when user clicks on the TextBox or the button area of an OmnibarMode, Omnibar still has focus anyway
153+ if ( e . OriginalSource . GetType ( ) is not { } originalSourceType ||
154+ originalSourceType == typeof ( TextBox ) ||
155+ originalSourceType == typeof ( OmnibarMode ) ||
156+ originalSourceType == typeof ( Omnibar ) )
157+ return ;
158+
97159 _isFocused = false ;
98160 UpdateVisualStates ( ) ;
99161 }
0 commit comments