From b4ed5bdc5fa1b4de193ea80e2be03944594ea46f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 10 Jul 2018 12:07:34 +0200 Subject: [PATCH] use Shift-keybindings to workaround eager list/tree keybindings, move picker when visible and focus changes --- .../ui/breadcrumbs/breadcrumbsWidget.ts | 13 ++++-- .../browser/parts/editor/editorBreadcrumbs.ts | 46 +++++++++++++------ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts index 29cee352905..aa7d97bb081 100644 --- a/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts +++ b/src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts @@ -49,6 +49,7 @@ export interface IBreadcrumbsWidgetStyles { } export interface IBreadcrumbsItemEvent { + type: 'select' | 'focus'; item: BreadcrumbsItem; node: HTMLElement; } @@ -139,6 +140,10 @@ export class BreadcrumbsWidget { this._domNode.focus(); } + isDOMFocused(): boolean { + return this._domNode === document.activeElement; + } + getFocused(): BreadcrumbsItem { return this._items[this._focusedItemIdx]; } @@ -149,12 +154,12 @@ export class BreadcrumbsWidget { focusPrev(): any { this._focus((this._focusedItemIdx - 1 + this._nodes.length) % this._nodes.length); - this._domNode.focus(); + // this._domNode.focus(); } focusNext(): any { this._focus((this._focusedItemIdx + 1) % this._nodes.length); - this._domNode.focus(); + // this._domNode.focus(); } private _focus(nth: number): void { @@ -168,7 +173,7 @@ export class BreadcrumbsWidget { dom.addClass(node, 'focused'); } } - this._onDidFocusItem.fire({ item: this._items[this._focusedItemIdx], node: this._nodes[this._focusedItemIdx] }); + this._onDidFocusItem.fire({ type: 'focus', item: this._items[this._focusedItemIdx], node: this._nodes[this._focusedItemIdx] }); } getSelected(): BreadcrumbsItem { @@ -190,7 +195,7 @@ export class BreadcrumbsWidget { dom.addClass(node, 'selected'); } } - this._onDidSelectItem.fire({ item: this._items[this._selectedItemIdx], node: this._nodes[this._selectedItemIdx] }); + this._onDidSelectItem.fire({ type: 'select', item: this._items[this._selectedItemIdx], node: this._nodes[this._selectedItemIdx] }); } setItems(items: BreadcrumbsItem[]): void { diff --git a/src/vs/workbench/browser/parts/editor/editorBreadcrumbs.ts b/src/vs/workbench/browser/parts/editor/editorBreadcrumbs.ts index f4dc0874688..542a8fb6294 100644 --- a/src/vs/workbench/browser/parts/editor/editorBreadcrumbs.ts +++ b/src/vs/workbench/browser/parts/editor/editorBreadcrumbs.ts @@ -11,7 +11,7 @@ import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel'; import { compareFileNames } from 'vs/base/common/comparers'; import { debounceEvent, Emitter, Event } from 'vs/base/common/event'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { dispose, IDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; import { dirname, isEqual } from 'vs/base/common/resources'; import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; @@ -99,10 +99,10 @@ class Item extends BreadcrumbsItem { export class EditorBreadcrumbs implements IEditorBreadcrumbs { static CK_BreadcrumbsVisible = new RawContextKey('breadcrumbsVisible', false); - static CK_BreadcrumbsFocused = new RawContextKey('breadcrumbsFocused', false); + static CK_BreadcrumbsActive = new RawContextKey('breadcrumbsActive', false); private readonly _ckBreadcrumbsVisible: IContextKey; - private readonly _ckBreadcrumbsFocused: IContextKey; + private readonly _ckBreadcrumbsActive: IContextKey; private readonly _cfEnabled: Config; @@ -111,6 +111,7 @@ export class EditorBreadcrumbs implements IEditorBreadcrumbs { private readonly _widget: BreadcrumbsWidget; private _breadcrumbsDisposables = new Array(); + private _breadcrumbsPickerShowing = false; constructor( container: HTMLElement, @@ -130,7 +131,8 @@ export class EditorBreadcrumbs implements IEditorBreadcrumbs { this._widget = new BreadcrumbsWidget(this._domNode); this._widget.onDidSelectItem(this._onDidSelectItem, this, this._disposables); - this._widget.onDidChangeFocus(val => this._ckBreadcrumbsFocused.set(val), undefined, this._disposables); + this._widget.onDidFocusItem(this._onDidSelectItem, this, this._disposables); + this._widget.onDidChangeFocus(this._updateCkBreadcrumbsActive, this, this._disposables); this._disposables.push(attachBreadcrumbsStyler(this._widget, this._themeService)); this._cfEnabled = Config.create(configurationService, 'breadcrumbs.enabled'); @@ -145,7 +147,7 @@ export class EditorBreadcrumbs implements IEditorBreadcrumbs { })); this._ckBreadcrumbsVisible = EditorBreadcrumbs.CK_BreadcrumbsVisible.bindTo(this._contextKeyService); - this._ckBreadcrumbsFocused = EditorBreadcrumbs.CK_BreadcrumbsFocused.bindTo(this._contextKeyService); + this._ckBreadcrumbsActive = EditorBreadcrumbs.CK_BreadcrumbsActive.bindTo(this._contextKeyService); } dispose(): void { @@ -222,6 +224,11 @@ export class EditorBreadcrumbs implements IEditorBreadcrumbs { return; } + if (event.type === 'focus' && !this._breadcrumbsPickerShowing) { + // focus change only moves the picker when already active + return; + } + this._editorGroup.focus(); this._contextViewService.showContextView({ getAnchor() { @@ -236,7 +243,7 @@ export class EditorBreadcrumbs implements IEditorBreadcrumbs { let ctor: IConstructorSignature2 = element instanceof FileElement ? BreadcrumbsFilePicker : BreadcrumbsOutlinePicker; let res = this._instantiationService.createInstance(ctor, container, element); res.layout({ width: 250, height: 300 }); - res.onDidPickElement(data => { + let listener = res.onDidPickElement(data => { this._contextViewService.hideContextView(); if (!data) { return; @@ -261,14 +268,22 @@ export class EditorBreadcrumbs implements IEditorBreadcrumbs { } }); - return res; + this._breadcrumbsPickerShowing = true; + this._updateCkBreadcrumbsActive(); + + return combinedDisposable([listener, res]); }, - onHide: () => { - this._widget.setSelected(undefined); - // this._widget.setFocused(undefined); + onHide: (data) => { + this._breadcrumbsPickerShowing = false; + this._updateCkBreadcrumbsActive(); } }); } + + private _updateCkBreadcrumbsActive(): void { + const value = this._widget.isDOMFocused() || this._breadcrumbsPickerShowing; + this._ckBreadcrumbsActive.set(value); + } } export abstract class BreadcrumbsPicker { @@ -512,7 +527,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'breadcrumbs.focusNext', weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), primary: KeyCode.RightArrow, - when: ContextKeyExpr.and(EditorBreadcrumbs.CK_BreadcrumbsVisible, EditorBreadcrumbs.CK_BreadcrumbsFocused), + secondary: [KeyMod.Shift | KeyCode.RightArrow], + when: ContextKeyExpr.and(EditorBreadcrumbs.CK_BreadcrumbsVisible, EditorBreadcrumbs.CK_BreadcrumbsActive), handler(accessor) { let groups = accessor.get(IEditorGroupsService); groups.activeGroup.breadcrumbs.focusNext(); @@ -522,7 +538,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'breadcrumbs.focusPrevious', weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), primary: KeyCode.LeftArrow, - when: ContextKeyExpr.and(EditorBreadcrumbs.CK_BreadcrumbsVisible, EditorBreadcrumbs.CK_BreadcrumbsFocused), + secondary: [KeyMod.Shift | KeyCode.LeftArrow], + when: ContextKeyExpr.and(EditorBreadcrumbs.CK_BreadcrumbsVisible, EditorBreadcrumbs.CK_BreadcrumbsActive), handler(accessor) { let groups = accessor.get(IEditorGroupsService); groups.activeGroup.breadcrumbs.focusPrev(); @@ -533,7 +550,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), primary: KeyCode.Enter, secondary: [KeyCode.UpArrow, KeyCode.Space], - when: ContextKeyExpr.and(EditorBreadcrumbs.CK_BreadcrumbsVisible, EditorBreadcrumbs.CK_BreadcrumbsFocused), + when: ContextKeyExpr.and(EditorBreadcrumbs.CK_BreadcrumbsVisible, EditorBreadcrumbs.CK_BreadcrumbsActive), handler(accessor) { let groups = accessor.get(IEditorGroupsService); groups.activeGroup.breadcrumbs.select(); @@ -543,7 +560,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ id: 'breadcrumbs.selectEditor', weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), primary: KeyCode.Escape, - when: ContextKeyExpr.and(EditorBreadcrumbs.CK_BreadcrumbsVisible, EditorBreadcrumbs.CK_BreadcrumbsFocused), + secondary: [KeyMod.Shift | KeyCode.Escape], + when: ContextKeyExpr.and(EditorBreadcrumbs.CK_BreadcrumbsVisible, EditorBreadcrumbs.CK_BreadcrumbsActive), handler(accessor) { let groups = accessor.get(IEditorGroupsService); groups.activeGroup.activeControl.focus(); -- GitLab