7
7
8
8
import 'vs/css!./quickInput' ;
9
9
import { Component } from 'vs/workbench/common/component' ;
10
- import { IQuickInputService , IPickOpenEntry , IPickOptions , IInputOptions } from 'vs/platform/quickinput/common/quickInput' ;
10
+ import { IQuickInputService , IPickOpenEntry , IPickOptions , IInputOptions , IQuickNavigateConfiguration } from 'vs/platform/quickinput/common/quickInput' ;
11
11
import { IPartService } from 'vs/workbench/services/part/common/partService' ;
12
12
import * as dom from 'vs/base/browser/dom' ;
13
13
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation' ;
@@ -73,6 +73,7 @@ export interface TextInputParameters extends BaseInputParameters {
73
73
}
74
74
75
75
interface QuickInputUI {
76
+ container : HTMLElement ;
76
77
checkAll : HTMLInputElement ;
77
78
inputBox : QuickInputBox ;
78
79
count : CountBadge ;
@@ -95,9 +96,10 @@ class PickOneController<T extends IPickOpenEntry> implements InputController<T>
95
96
public resolve : ( ok ?: true | Thenable < never > ) => void ;
96
97
public progress : ( value : T ) => void ;
97
98
private closed = false ;
99
+ private quickNavigate = false ;
98
100
private disposables : IDisposable [ ] = [ ] ;
99
101
100
- constructor ( ui : QuickInputUI , parameters : PickOneParameters < T > ) {
102
+ constructor ( private ui : QuickInputUI , parameters : PickOneParameters < T > ) {
101
103
this . result = new TPromise < T > ( ( resolve , reject , progress ) => {
102
104
this . resolve = ok => resolve ( ok === true ? < T > ui . list . getFocusedElements ( ) [ 0 ] : ok ) ;
103
105
this . progress = progress ;
@@ -143,6 +145,53 @@ class PickOneController<T extends IPickOpenEntry> implements InputController<T>
143
145
} ) ;
144
146
}
145
147
148
+ configureQuickNavigate ( quickNavigate : IQuickNavigateConfiguration ) {
149
+ if ( this . quickNavigate ) {
150
+ return ;
151
+ }
152
+ this . quickNavigate = true ;
153
+
154
+ this . disposables . push ( dom . addDisposableListener ( this . ui . container , dom . EventType . KEY_UP , ( e : KeyboardEvent ) => {
155
+ const keyboardEvent : StandardKeyboardEvent = new StandardKeyboardEvent ( e as KeyboardEvent ) ;
156
+ const keyCode = keyboardEvent . keyCode ;
157
+
158
+ // Select element when keys are pressed that signal it
159
+ const quickNavKeys = quickNavigate . keybindings ;
160
+ const wasTriggerKeyPressed = keyCode === KeyCode . Enter || quickNavKeys . some ( k => {
161
+ const [ firstPart , chordPart ] = k . getParts ( ) ;
162
+ if ( chordPart ) {
163
+ return false ;
164
+ }
165
+
166
+ if ( firstPart . shiftKey && keyCode === KeyCode . Shift ) {
167
+ if ( keyboardEvent . ctrlKey || keyboardEvent . altKey || keyboardEvent . metaKey ) {
168
+ return false ; // this is an optimistic check for the shift key being used to navigate back in quick open
169
+ }
170
+
171
+ return true ;
172
+ }
173
+
174
+ if ( firstPart . altKey && keyCode === KeyCode . Alt ) {
175
+ return true ;
176
+ }
177
+
178
+ if ( firstPart . ctrlKey && keyCode === KeyCode . Ctrl ) {
179
+ return true ;
180
+ }
181
+
182
+ if ( firstPart . metaKey && keyCode === KeyCode . Meta ) {
183
+ return true ;
184
+ }
185
+
186
+ return false ;
187
+ } ) ;
188
+
189
+ if ( wasTriggerKeyPressed ) {
190
+ this . ui . close ( true ) ;
191
+ }
192
+ } ) ) ;
193
+ }
194
+
146
195
private dispose ( ) {
147
196
this . closed = true ;
148
197
this . disposables = dispose ( this . disposables ) ;
@@ -301,7 +350,6 @@ export class QuickInputService extends Component implements IQuickInputService {
301
350
private static readonly MAX_WIDTH = 600 ; // Max total width of quick open widget
302
351
303
352
private layoutDimensions : dom . Dimension ;
304
- private container : HTMLElement ;
305
353
private filterContainer : HTMLElement ;
306
354
private countContainer : HTMLElement ;
307
355
private okContainer : HTMLElement ;
@@ -348,16 +396,16 @@ export class QuickInputService extends Component implements IQuickInputService {
348
396
}
349
397
350
398
private create ( ) {
351
- if ( this . container ) {
399
+ if ( this . ui ) {
352
400
return ;
353
401
}
354
402
355
403
const workbench = document . getElementById ( this . partService . getWorkbenchElementId ( ) ) ;
356
- this . container = dom . append ( workbench , $ ( '.quick-input-widget' ) ) ;
357
- this . container . tabIndex = - 1 ;
358
- this . container . style . display = 'none' ;
404
+ const container = dom . append ( workbench , $ ( '.quick-input-widget' ) ) ;
405
+ container . tabIndex = - 1 ;
406
+ container . style . display = 'none' ;
359
407
360
- const headerContainer = dom . append ( this . container , $ ( '.quick-input-header' ) ) ;
408
+ const headerContainer = dom . append ( container , $ ( '.quick-input-header' ) ) ;
361
409
362
410
const checkAll = < HTMLInputElement > dom . append ( headerContainer , $ ( 'input.quick-input-check-all' ) ) ;
363
411
checkAll . type = 'checkbox' ;
@@ -390,13 +438,13 @@ export class QuickInputService extends Component implements IQuickInputService {
390
438
}
391
439
} ) ) ;
392
440
393
- const message = dom . append ( this . container , $ ( '.quick-input-message' ) ) ;
441
+ const message = dom . append ( container , $ ( '.quick-input-message' ) ) ;
394
442
395
- this . progressBar = new ProgressBar ( this . container ) ;
443
+ this . progressBar = new ProgressBar ( container ) ;
396
444
dom . addClass ( this . progressBar . getContainer ( ) , 'quick-input-progress' ) ;
397
445
this . toUnbind . push ( attachProgressBarStyler ( this . progressBar , this . themeService ) ) ;
398
446
399
- const list = this . instantiationService . createInstance ( QuickInputList , this . container ) ;
447
+ const list = this . instantiationService . createInstance ( QuickInputList , container ) ;
400
448
this . toUnbind . push ( list ) ;
401
449
this . toUnbind . push ( list . onAllVisibleCheckedChanged ( checked => {
402
450
checkAll . checked = checked ;
@@ -424,21 +472,21 @@ export class QuickInputService extends Component implements IQuickInputService {
424
472
} )
425
473
) ;
426
474
427
- this . toUnbind . push ( dom . addDisposableListener ( this . container , 'focusout' , ( e : FocusEvent ) => {
428
- if ( e . relatedTarget === this . container ) {
475
+ this . toUnbind . push ( dom . addDisposableListener ( container , 'focusout' , ( e : FocusEvent ) => {
476
+ if ( e . relatedTarget === container ) {
429
477
( < HTMLElement > e . target ) . focus ( ) ;
430
478
return ;
431
479
}
432
480
for ( let element = < Element > e . relatedTarget ; element ; element = element . parentElement ) {
433
- if ( element === this . container ) {
481
+ if ( element === container ) {
434
482
return ;
435
483
}
436
484
}
437
485
if ( ! this . ignoreFocusLost && ! this . environmentService . args [ 'sticky-quickopen' ] && this . configurationService . getValue ( CLOSE_ON_FOCUS_LOST_CONFIG ) ) {
438
486
this . close ( undefined , true ) ;
439
487
}
440
488
} ) ) ;
441
- this . toUnbind . push ( dom . addDisposableListener ( this . container , dom . EventType . KEY_DOWN , ( e : KeyboardEvent ) => {
489
+ this . toUnbind . push ( dom . addDisposableListener ( container , dom . EventType . KEY_DOWN , ( e : KeyboardEvent ) => {
442
490
const event = new StandardKeyboardEvent ( e ) ;
443
491
switch ( event . keyCode ) {
444
492
case KeyCode . Enter :
@@ -453,7 +501,7 @@ export class QuickInputService extends Component implements IQuickInputService {
453
501
break ;
454
502
case KeyCode . Tab :
455
503
if ( ! event . altKey && ! event . ctrlKey && ! event . metaKey ) {
456
- const inputs = [ ] . slice . call ( this . container . querySelectorAll ( 'input' ) )
504
+ const inputs = [ ] . slice . call ( container . querySelectorAll ( 'input' ) )
457
505
. filter ( input => input . style . display !== 'none' ) ;
458
506
if ( event . shiftKey && event . target === inputs [ 0 ] ) {
459
507
dom . EventHelper . stop ( e , true ) ;
@@ -469,7 +517,7 @@ export class QuickInputService extends Component implements IQuickInputService {
469
517
470
518
this . toUnbind . push ( this . quickOpenService . onShow ( ( ) => this . close ( ) ) ) ;
471
519
472
- this . ui = { checkAll, inputBox, count, message, list, close : ok => this . close ( ok ) } ;
520
+ this . ui = { container , checkAll, inputBox, count, message, list, close : ok => this . close ( ok ) } ;
473
521
this . updateStyles ( ) ;
474
522
}
475
523
@@ -483,7 +531,7 @@ export class QuickInputService extends Component implements IQuickInputService {
483
531
const result = resolved
484
532
. then ( ( ) => {
485
533
this . inQuickOpen ( 'quickInput' , false ) ;
486
- this . container . style . display = 'none' ;
534
+ this . ui . container . style . display = 'none' ;
487
535
if ( ! focusLost ) {
488
536
this . restoreFocus ( ) ;
489
537
}
@@ -493,7 +541,7 @@ export class QuickInputService extends Component implements IQuickInputService {
493
541
}
494
542
}
495
543
this . inQuickOpen ( 'quickInput' , false ) ;
496
- this . container . style . display = 'none' ;
544
+ this . ui . container . style . display = 'none' ;
497
545
if ( ! focusLost ) {
498
546
this . restoreFocus ( ) ;
499
547
}
@@ -540,7 +588,7 @@ export class QuickInputService extends Component implements IQuickInputService {
540
588
this . controller . resolve ( ) ;
541
589
}
542
590
543
- this . container . setAttribute ( 'data-type' , parameters . type ) ;
591
+ this . ui . container . setAttribute ( 'data-type' , parameters . type ) ;
544
592
545
593
this . ignoreFocusLost = parameters . ignoreFocusLost ;
546
594
@@ -556,10 +604,10 @@ export class QuickInputService extends Component implements IQuickInputService {
556
604
this . ui . message . style . display = this . controller . showUI . message ? '' : 'none' ;
557
605
this . ui . list . display ( this . controller . showUI . list ) ;
558
606
559
- if ( this . container . style . display === 'none' ) {
607
+ if ( this . ui . container . style . display === 'none' ) {
560
608
this . inQuickOpen ( 'quickInput' , true ) ;
561
609
}
562
- this . container . style . display = '' ;
610
+ this . ui . container . style . display = '' ;
563
611
this . updateLayout ( ) ;
564
612
this . ui . inputBox . setFocus ( ) ;
565
613
@@ -608,9 +656,12 @@ export class QuickInputService extends Component implements IQuickInputService {
608
656
}
609
657
}
610
658
611
- navigate ( next : boolean ) {
659
+ navigate ( next : boolean , quickNavigate ?: IQuickNavigateConfiguration ) {
612
660
if ( this . isDisplayed ( ) && this . ui . list . isDisplayed ( ) ) {
613
661
this . ui . list . focus ( next ? 'Next' : 'Previous' ) ;
662
+ if ( quickNavigate && this . controller instanceof PickOneController ) {
663
+ this . controller . configureQuickNavigate ( quickNavigate ) ;
664
+ }
614
665
}
615
666
}
616
667
@@ -628,11 +679,11 @@ export class QuickInputService extends Component implements IQuickInputService {
628
679
}
629
680
630
681
private updateLayout ( ) {
631
- if ( this . layoutDimensions && this . container ) {
682
+ if ( this . layoutDimensions && this . ui ) {
632
683
const titlebarOffset = this . partService . getTitleBarOffset ( ) ;
633
- this . container . style . top = `${ titlebarOffset } px` ;
684
+ this . ui . container . style . top = `${ titlebarOffset } px` ;
634
685
635
- const style = this . container . style ;
686
+ const style = this . ui . container . style ;
636
687
const width = Math . min ( this . layoutDimensions . width * 0.62 /* golden cut */ , QuickInputService . MAX_WIDTH ) ;
637
688
style . width = width + 'px' ;
638
689
style . marginLeft = '-' + ( width / 2 ) + 'px' ;
@@ -647,20 +698,20 @@ export class QuickInputService extends Component implements IQuickInputService {
647
698
if ( this . ui ) {
648
699
this . ui . inputBox . style ( theme ) ;
649
700
}
650
- if ( this . container ) {
701
+ if ( this . ui ) {
651
702
const sideBarBackground = theme . getColor ( SIDE_BAR_BACKGROUND ) ;
652
- this . container . style . backgroundColor = sideBarBackground ? sideBarBackground . toString ( ) : undefined ;
703
+ this . ui . container . style . backgroundColor = sideBarBackground ? sideBarBackground . toString ( ) : undefined ;
653
704
const sideBarForeground = theme . getColor ( SIDE_BAR_FOREGROUND ) ;
654
- this . container . style . color = sideBarForeground ? sideBarForeground . toString ( ) : undefined ;
705
+ this . ui . container . style . color = sideBarForeground ? sideBarForeground . toString ( ) : undefined ;
655
706
const contrastBorderColor = theme . getColor ( contrastBorder ) ;
656
- this . container . style . border = contrastBorderColor ? `1px solid ${ contrastBorderColor } ` : undefined ;
707
+ this . ui . container . style . border = contrastBorderColor ? `1px solid ${ contrastBorderColor } ` : undefined ;
657
708
const widgetShadowColor = theme . getColor ( widgetShadow ) ;
658
- this . container . style . boxShadow = widgetShadowColor ? `0 5px 8px ${ widgetShadowColor } ` : undefined ;
709
+ this . ui . container . style . boxShadow = widgetShadowColor ? `0 5px 8px ${ widgetShadowColor } ` : undefined ;
659
710
}
660
711
}
661
712
662
713
private isDisplayed ( ) {
663
- return this . container && this . container . style . display !== 'none' ;
714
+ return this . ui && this . ui . container . style . display !== 'none' ;
664
715
}
665
716
}
666
717
0 commit comments