Skip to content

Commit

Permalink
Add quickNavigate (#29096)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrmarti committed Aug 8, 2018
1 parent 0659543 commit 772cd46
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 51 deletions.
7 changes: 7 additions & 0 deletions src/vs/platform/quickinput/common/quickInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ export interface IPickOptions<T extends IQuickPickItem> {
*/
canPickMany?: boolean;

/**
* enables quick navigate in the picker to open an element without typing
*/
quickNavigate?: IQuickNavigateConfiguration;

/**
* a context key to set when this picker is active
*/
Expand Down Expand Up @@ -146,6 +151,8 @@ export interface IQuickPick<T extends IQuickPickItem> extends IQuickInput {

matchOnDetail: boolean;

quickNavigate: IQuickNavigateConfiguration | undefined;

activeItems: ReadonlyArray<T>;

readonly onDidChangeActive: Event<T[]>;
Expand Down
104 changes: 53 additions & 51 deletions src/vs/workbench/browser/parts/quickinput/quickInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,8 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
private selectedItemsUpdated = false;
private selectedItemsToConfirm: T[] = [];
private onDidChangeSelectionEmitter = new Emitter<T[]>();
private quickNavigate = false;

quickNavigate: IQuickNavigateConfiguration;

constructor(ui: QuickInputUI) {
super(ui);
Expand Down Expand Up @@ -498,11 +499,60 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
this._selectedItems = checkedItems as T[];
this.onDidChangeSelectionEmitter.fire(checkedItems as T[]);
}),
this.registerQuickNavigation()
);
}
super.show();
}

private registerQuickNavigation() {
return dom.addDisposableListener(this.ui.container, dom.EventType.KEY_UP, (e: KeyboardEvent) => {
if (this.canSelectMany || !this.quickNavigate) {
return;
}

const keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e as KeyboardEvent);
const keyCode = keyboardEvent.keyCode;

// Select element when keys are pressed that signal it
const quickNavKeys = this.quickNavigate.keybindings;
const wasTriggerKeyPressed = keyCode === KeyCode.Enter || quickNavKeys.some(k => {
const [firstPart, chordPart] = k.getParts();
if (chordPart) {
return false;
}

if (firstPart.shiftKey && keyCode === KeyCode.Shift) {
if (keyboardEvent.ctrlKey || keyboardEvent.altKey || keyboardEvent.metaKey) {
return false; // this is an optimistic check for the shift key being used to navigate back in quick open
}

return true;
}

if (firstPart.altKey && keyCode === KeyCode.Alt) {
return true;
}

if (firstPart.ctrlKey && keyCode === KeyCode.Ctrl) {
return true;
}

if (firstPart.metaKey && keyCode === KeyCode.Meta) {
return true;
}

return false;
});

if (wasTriggerKeyPressed && this.activeItems[0]) {
this._selectedItems = [this.activeItems[0]];
this.onDidChangeSelectionEmitter.fire(this.selectedItems);
this.onDidAcceptEmitter.fire();
}
});
}

protected update() {
super.update();
if (!this.visible) {
Expand Down Expand Up @@ -556,55 +606,6 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
this.ui.list.matchOnDetail = this.matchOnDetail;
this.ui.setVisibilities(this.canSelectMany ? { title: !!this.title || !!this.step, checkAll: true, inputBox: true, visibleCount: true, count: true, ok: true, list: true } : { title: !!this.title || !!this.step, inputBox: true, visibleCount: true, list: true });
}

configureQuickNavigate(quickNavigate: IQuickNavigateConfiguration) {
if (this.canSelectMany || this.quickNavigate) {
return;
}
this.quickNavigate = true;

this.disposables.push(dom.addDisposableListener(this.ui.container, dom.EventType.KEY_UP, (e: KeyboardEvent) => {
const keyboardEvent: StandardKeyboardEvent = new StandardKeyboardEvent(e as KeyboardEvent);
const keyCode = keyboardEvent.keyCode;

// Select element when keys are pressed that signal it
const quickNavKeys = quickNavigate.keybindings;
const wasTriggerKeyPressed = keyCode === KeyCode.Enter || quickNavKeys.some(k => {
const [firstPart, chordPart] = k.getParts();
if (chordPart) {
return false;
}

if (firstPart.shiftKey && keyCode === KeyCode.Shift) {
if (keyboardEvent.ctrlKey || keyboardEvent.altKey || keyboardEvent.metaKey) {
return false; // this is an optimistic check for the shift key being used to navigate back in quick open
}

return true;
}

if (firstPart.altKey && keyCode === KeyCode.Alt) {
return true;
}

if (firstPart.ctrlKey && keyCode === KeyCode.Ctrl) {
return true;
}

if (firstPart.metaKey && keyCode === KeyCode.Meta) {
return true;
}

return false;
});

if (wasTriggerKeyPressed && this.activeItems[0]) {
this._selectedItems = [this.activeItems[0]];
this.onDidChangeSelectionEmitter.fire(this.selectedItems);
this.onDidAcceptEmitter.fire();
}
}));
}
}

class InputBox extends QuickInput implements IInputBox {
Expand Down Expand Up @@ -1020,6 +1021,7 @@ export class QuickInputService extends Component implements IQuickInputService {
input.ignoreFocusOut = options.ignoreFocusLost;
input.matchOnDescription = options.matchOnDescription;
input.matchOnDetail = options.matchOnDetail;
input.quickNavigate = options.quickNavigate;
input.contextKey = options.contextKey;
input.busy = true;
TPromise.join([picks, options.activeItem])
Expand Down Expand Up @@ -1207,7 +1209,7 @@ export class QuickInputService extends Component implements IQuickInputService {
if (this.isDisplayed() && this.ui.list.isDisplayed()) {
this.ui.list.focus(next ? 'Next' : 'Previous');
if (quickNavigate && this.controller instanceof QuickPick) {
this.controller.configureQuickNavigate(quickNavigate);
this.controller.quickNavigate = quickNavigate;
}
}
}
Expand Down

0 comments on commit 772cd46

Please sign in to comment.