22using Avalonia . Controls ;
33using Avalonia . Controls . Templates ;
44using Avalonia . Data ;
5- using Avalonia . Controls . Primitives ;
6- using Avalonia . VisualTree ;
5+ using Avalonia . Input ;
6+ using Avalonia . Media ;
77using Avalonia . Threading ;
88using DirectorPrompt . Services ;
99
1010namespace DirectorPrompt . Views . Components ;
1111
1212public sealed class PathComboBox : ComboBox
1313{
14- private Popup ? popup ;
15- private Control ? remotePopupContent ;
14+ private Border ? remotePopupContent ;
15+ private ListBox ? remoteList ;
16+ private bool suppressDropDownClosed ;
1617
1718 protected override Type StyleKeyOverride => typeof ( ComboBox ) ;
1819
@@ -80,7 +81,7 @@ private void OnDropDownOpened(object? sender, EventArgs e)
8081
8182 private void OnDropDownClosed ( object ? sender , EventArgs e )
8283 {
83- if ( ! RemotePopupHost . IsRemote ( this ) )
84+ if ( ! RemotePopupHost . IsRemote ( this ) || suppressDropDownClosed )
8485 return ;
8586
8687 HideRemoteDropdown ( ) ;
@@ -91,18 +92,50 @@ private void ShowRemoteDropdown()
9192 if ( remotePopupContent is not null )
9293 return ;
9394
94- popup = this . GetVisualDescendants ( ) . OfType < Popup > ( ) . FirstOrDefault ( ) ;
95+ suppressDropDownClosed = true ;
96+ IsDropDownOpen = false ;
97+ suppressDropDownClosed = false ;
9598
96- if ( popup ? . Child is not Control content )
97- return ;
99+ var list = new ListBox
100+ {
101+ ItemTemplate = ItemTemplate
102+ } ;
98103
99- popup . Child = null ;
100- remotePopupContent = content ;
104+ if ( ItemsSource is not null )
105+ {
106+ list . ItemsSource = ItemsSource ;
107+ list . SelectedItem = SelectedItem ;
108+ }
109+ else
110+ {
111+ list . ItemsSource = Items
112+ . Cast < object > ( )
113+ . Select ( static item => item is ComboBoxItem comboItem ? comboItem . Content : item )
114+ . ToArray ( ) ;
115+ list . SelectedIndex = SelectedIndex ;
116+ }
117+
118+ list . SelectionChanged += OnRemoteSelectionChanged ;
119+ list . KeyDown += OnRemoteListKeyDown ;
120+
121+ var content = new Border
122+ {
123+ MinHeight = 36 ,
124+ MaxHeight = 320 ,
125+ Padding = new Thickness ( 4 ) ,
126+ Background = new SolidColorBrush ( Color . FromRgb ( 32 , 32 , 32 ) ) ,
127+ BorderBrush = new SolidColorBrush ( Color . FromRgb ( 92 , 92 , 92 ) ) ,
128+ BorderThickness = new Thickness ( 1 ) ,
129+ Child = list
130+ } ;
131+
132+ remoteList = list ;
133+ remotePopupContent = content ;
101134
102135 if ( ! RemotePopupHost . Show ( this , content , Bounds . Width , RestoreRemotePopupContent ) )
103136 {
104137 remotePopupContent = null ;
105- popup . Child = content ;
138+ remoteList = null ;
106139 }
107140 }
108141
@@ -111,18 +144,47 @@ private void HideRemoteDropdown()
111144 if ( remotePopupContent is null )
112145 return ;
113146
114- var content = RemotePopupHost . Hide ( this ) ?? remotePopupContent ;
147+ RemotePopupHost . Hide ( this ) ;
115148 remotePopupContent = null ;
149+ remoteList = null ;
150+ }
116151
117- if ( popup is not null )
118- popup . Child = content ;
152+ private void OnRemoteSelectionChanged ( object ? sender , SelectionChangedEventArgs e )
153+ {
154+ CommitRemoteSelection ( ) ;
155+ }
156+
157+ private void CommitRemoteSelection ( )
158+ {
159+ if ( remoteList is null || remoteList . SelectedIndex < 0 )
160+ return ;
161+
162+ if ( ItemsSource is not null )
163+ SelectedItem = remoteList ? . SelectedItem ;
164+ else
165+ SelectedIndex = remoteList ? . SelectedIndex ?? - 1 ;
166+
167+ HideRemoteDropdown ( ) ;
119168 }
120169
121170 private void RestoreRemotePopupContent ( Control content )
122171 {
123172 remotePopupContent = null ;
173+ remoteList = null ;
174+ }
124175
125- if ( popup is not null )
126- popup . Child = content ;
176+ private void OnRemoteListKeyDown ( object ? sender , KeyEventArgs e )
177+ {
178+ if ( e . Key == Key . Escape )
179+ {
180+ HideRemoteDropdown ( ) ;
181+ e . Handled = true ;
182+ }
183+ else if ( e . Key == Key . Enter )
184+ {
185+ if ( remoteList is not null )
186+ CommitRemoteSelection ( ) ;
187+ e . Handled = true ;
188+ }
127189 }
128190}
0 commit comments