@@ -120,7 +120,8 @@ private GridViewDataSource LoadData()
120120 return new GridViewDataSource ( items ) ;
121121 }
122122
123- private void ApplyFilter ( ) {
123+ private void ApplyFilter ( )
124+ {
124125 List < GridViewRow > itemList = GridViewHelpers . FilterData ( _itemSource . GridViewRowList , _applicationData . Filter ?? string . Empty ) ;
125126 // Set the ListView to show only the subset defined by the filter
126127 _listView . Source = new GridViewDataSource ( itemList ) ;
@@ -149,50 +150,72 @@ private Window CreateTopLevelWindow()
149150 Width = Dim . Fill ( _applicationData . MinUI ? - 1 : 0 ) ,
150151 Height = Dim . Fill ( _applicationData . MinUI ? - 1 : 1 )
151152 } ;
152-
153- if ( _applicationData . MinUI ) {
153+
154+ if ( _applicationData . MinUI )
155+ {
154156 win . Border . BorderStyle = BorderStyle . None ;
155- }
156-
157+ }
158+
157159 Application . Top . Add ( win ) ;
158160 return win ;
159161 }
160162
161163 private void AddStatusBar ( bool visible )
162164 {
163- var statusBar = new StatusBar (
164- _applicationData . OutputMode != OutputModeOption . None
165- ? new StatusItem [ ]
165+ var statusItems = new List < StatusItem > ( ) ;
166+ if ( _applicationData . OutputMode != OutputModeOption . None )
167+ {
168+ // Use Key.Unknown for SPACE with no delegate because ListView already
169+ // handles SPACE
170+ statusItems . Add ( new StatusItem ( Key . Unknown , "~SPACE~ Select Item" , null ) ) ;
171+ }
172+
173+ if ( _applicationData . OutputMode == OutputModeOption . Multiple )
174+ {
175+ statusItems . Add ( new StatusItem ( Key . A | Key . CtrlMask , "~CTRL-A~ Select All" , ( ) =>
176+ {
177+ // This selects only the items that match the Filter
178+ var gvds = _listView . Source as GridViewDataSource ;
179+ gvds . GridViewRowList . ForEach ( i => i . IsMarked = true ) ;
180+ _listView . SetNeedsDisplay ( ) ;
181+ } ) ) ;
182+
183+ // Ctrl-D is commonly used in GUIs for select-none
184+ statusItems . Add ( new StatusItem ( Key . D | Key . CtrlMask , "~CTRL-D~ Select None" , ( ) =>
185+ {
186+ // This un-selects only the items that match the Filter
187+ var gvds = _listView . Source as GridViewDataSource ;
188+ gvds . GridViewRowList . ForEach ( i => i . IsMarked = false ) ;
189+ _listView . SetNeedsDisplay ( ) ;
190+ } ) ) ;
191+ }
192+
193+ if ( _applicationData . OutputMode != OutputModeOption . None )
194+ {
195+ statusItems . Add ( new StatusItem ( Key . Enter , "~ENTER~ Accept" , ( ) =>
196+ {
197+ if ( Application . Top . MostFocused == _listView )
166198 {
167- // Use Key.Unknown for SPACE with no delegate because ListView already
168- // handles SPACE
169- new StatusItem ( Key . Unknown , "~SPACE~ Mark Item" , null ) ,
170- new StatusItem ( Key . Enter , "~ENTER~ Accept" , ( ) =>
199+ // If nothing was explicitly marked, we return the item that was selected
200+ // when ENTER is pressed in Single mode. If something was previously selected
201+ // (using SPACE) then honor that as the single item to return
202+ if ( _applicationData . OutputMode == OutputModeOption . Single &&
203+ _itemSource . GridViewRowList . Find ( i => i . IsMarked ) == null )
171204 {
172- if ( Application . Top . MostFocused == _listView )
173- {
174- // If nothing was explicitly marked, we return the item that was selected
175- // when ENTER is pressed in Single mode. If something was previously selected
176- // (using SPACE) then honor that as the single item to return
177- if ( _applicationData . OutputMode == OutputModeOption . Single &&
178- _itemSource . GridViewRowList . Find ( i => i . IsMarked ) == null )
179- {
180- _listView . MarkUnmarkRow ( ) ;
181- }
182- Accept ( ) ;
183- }
184- else if ( Application . Top . MostFocused == _filterField )
185- {
186- _listView . SetFocus ( ) ;
187- }
188- } ) ,
189- new StatusItem ( Key . Esc , "~ESC~ Close" , ( ) => Close ( ) )
205+ _listView . MarkUnmarkRow ( ) ;
206+ }
207+ Accept ( ) ;
190208 }
191- : new StatusItem [ ]
209+ else if ( Application . Top . MostFocused == _filterField )
192210 {
193- new StatusItem ( Key . Esc , "~ESC~ Close" , ( ) => Close ( ) )
211+ _listView . SetFocus ( ) ;
194212 }
195- ) ;
213+ } ) ) ;
214+ }
215+
216+ statusItems . Add ( new StatusItem ( Key . Esc , "~ESC~ Close" , ( ) => Close ( ) ) ) ;
217+
218+ var statusBar = new StatusBar ( statusItems . ToArray ( ) ) ;
196219 statusBar . Visible = visible ;
197220 Application . Top . Add ( statusBar ) ;
198221 }
@@ -220,7 +243,6 @@ private void CalculateColumnWidths(List<string> gridHeaders)
220243 {
221244 listViewColumnWidths [ index ] = len ;
222245 }
223-
224246 index ++ ;
225247 }
226248 }
@@ -262,6 +284,13 @@ private void AddFilter(Window win)
262284 Width = Dim . Fill ( ) - _filterLabel . Text . Length
263285 } ;
264286
287+ // TextField captures Ctrl-A (select all text) and Ctrl-D (delete backwards)
288+ // In OCGV these are used for select-all/none of items. Selecting items is more
289+ // common than editing the filter field so we turn them off in the filter textview.
290+ // BACKSPACE still works for delete backwards
291+ _filterField . ClearKeybinding ( Key . A | Key . CtrlMask ) ;
292+ _filterField . ClearKeybinding ( Key . D | Key . CtrlMask ) ;
293+
265294 var filterErrorLabel = new Label ( string . Empty )
266295 {
267296 X = Pos . Right ( _filterLabel ) + 1 ,
@@ -327,7 +356,8 @@ private void AddHeaders(Window win, List<string> gridHeaders)
327356 }
328357 }
329358
330- if ( ! _applicationData . MinUI ) {
359+ if ( ! _applicationData . MinUI )
360+ {
331361 var headerLine = new Label ( headerLineText . ToString ( ) )
332362 {
333363 X = 0 ,
@@ -344,7 +374,7 @@ private void AddListView(Window win)
344374 if ( ! _applicationData . MinUI )
345375 {
346376 _listView . Y = Pos . Bottom ( _filterLabel ) + 3 ; // 1 for space, 1 for header, 1 for header underline
347- }
377+ }
348378 else
349379 {
350380 _listView . Y = 1 ; // 1 for space, 1 for header, 1 for header underline
0 commit comments