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 ;
@@ -17,12 +18,17 @@ namespace Files.App.Controls
1718 [ TemplatePart ( Name = "PART_ModesHostGrid" , Type = typeof ( Grid ) ) ]
1819 // Visual states
1920 [ TemplateVisualState ( Name = "Focused" , GroupName = "FocusStates" ) ]
20- [ TemplateVisualState ( Name = "Unfocused " , GroupName = "FocusStates" ) ]
21+ [ TemplateVisualState ( Name = "Normal " , GroupName = "FocusStates" ) ]
2122 public partial class Omnibar : Control
2223 {
2324 private const string ModesHostGrid = "PART_ModesHostGrid" ;
25+ private const string AutoSuggestPopup = "PART_AutoSuggestPopup" ;
26+ private const string AutoSuggestBoxBorder = "PART_AutoSuggestBoxBorder" ;
2427
2528 private Grid ? _modesHostGrid ;
29+ private Popup ? _autoSuggestPopup ;
30+ private Border ? _autoSuggestBoxBorder ;
31+ private bool _wasAscendantFocused ;
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,13 @@ 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 ;
6781 }
6882
83+ _modesHostGrid . SizeChanged += _modesHostGrid_SizeChanged ;
84+
85+ var parentElement = this . FindAscendant < FrameworkElement > ( ) ! ;
86+ parentElement . PointerPressed += ParentElement_PointerPressed ;
6987 GotFocus += Omnibar_GotFocus ;
7088 LostFocus += Omnibar_LostFocus ;
7189
@@ -74,7 +92,29 @@ protected override void OnApplyTemplate()
7492 base . OnApplyTemplate ( ) ;
7593 }
7694
77- // Private methods
95+ // Methods
96+
97+ internal void ChangeExpandedMode ( OmnibarMode modeToExpand )
98+ {
99+ if ( _modesHostGrid is null || Modes is null )
100+ throw new NullReferenceException ( ) ;
101+
102+ // Reset
103+ foreach ( var column in _modesHostGrid . ColumnDefinitions )
104+ column . Width = GridLength . Auto ;
105+ foreach ( var mode in Modes )
106+ {
107+ VisualStateManager . GoToState ( mode , "InactiveIcon" , true ) ;
108+ VisualStateManager . GoToState ( mode , "Collapsed" , true ) ;
109+ }
110+
111+ // Expand the given mode
112+ VisualStateManager . GoToState ( modeToExpand , "ActiveIcon" , true ) ;
113+ VisualStateManager . GoToState ( modeToExpand , "Visible" , true ) ;
114+ _modesHostGrid . ColumnDefinitions [ _modesHostGrid . Children . IndexOf ( modeToExpand ) ] . Width = new ( 1 , GridUnitType . Star ) ;
115+
116+ CurrentActiveMode = modeToExpand ;
117+ }
78118
79119 private void UpdateVisualStates ( )
80120 {
@@ -86,16 +126,45 @@ private void UpdateVisualStates()
86126
87127 // Events
88128
129+ private void _modesHostGrid_SizeChanged ( object sender , SizeChangedEventArgs e )
130+ {
131+ _autoSuggestBoxBorder ! . Width = _modesHostGrid ! . ActualWidth ;
132+ }
133+
134+ private void ParentElement_PointerPressed ( object sender , PointerRoutedEventArgs e )
135+ {
136+ // Lost focus
137+ if ( _isFocused )
138+ {
139+ _isFocused = _wasAscendantFocused = false ;
140+ UpdateVisualStates ( ) ;
141+
142+ return ;
143+ }
144+
145+ _wasAscendantFocused = true ;
146+ }
147+
89148 private void Omnibar_GotFocus ( object sender , RoutedEventArgs e )
90149 {
150+ if ( _wasAscendantFocused )
151+ {
152+ _isFocused = _wasAscendantFocused = false ;
153+ return ;
154+ }
155+
91156 _isFocused = true ;
92157 UpdateVisualStates ( ) ;
158+
159+ _autoSuggestPopup ! . IsOpen = true ;
93160 }
94161
95162 private void Omnibar_LostFocus ( object sender , RoutedEventArgs e )
96163 {
97- _isFocused = false ;
164+ _isFocused = _wasAscendantFocused = false ;
98165 UpdateVisualStates ( ) ;
166+
167+ _autoSuggestPopup ! . IsOpen = false ;
99168 }
100169 }
101170}
0 commit comments