fix(tree): 🐛 allow navigating between breadcrumbs using arrow keys

This commit is contained in:
João Moreno 2021-11-05 16:23:07 +01:00
parent b5ac86ad3e
commit e5bcb02e1e
No known key found for this signature in database
GPG key ID: 896B853774D1A575
5 changed files with 42 additions and 15 deletions

19
.vscode/settings.json vendored
View file

@ -42,9 +42,7 @@
}
],
"eslint.options": {
"rulePaths": [
"./build/lib/eslint"
]
"rulePaths": ["./build/lib/eslint"]
},
"typescript.tsdk": "node_modules/typescript/lib",
"npm.exclude": "**/extensions/**",
@ -54,15 +52,11 @@
"typescript.preferences.quoteStyle": "single",
"json.schemas": [
{
"fileMatch": [
"cgmanifest.json"
],
"fileMatch": ["cgmanifest.json"],
"url": "./.vscode/cgmanifest.schema.json"
},
{
"fileMatch": [
"cglicenses.json"
],
"fileMatch": ["cglicenses.json"],
"url": "./.vscode/cglicenses.schema.json"
}
],
@ -73,16 +67,17 @@
"gulp.autoDetect": "off",
"files.insertFinalNewline": true,
"[plaintext]": {
"files.insertFinalNewline": false,
"files.insertFinalNewline": false
},
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features",
"editor.formatOnSave": true,
"editor.formatOnSave": true
},
"[javascript]": {
"editor.defaultFormatter": "vscode.typescript-language-features",
"editor.formatOnSave": true,
"editor.formatOnSave": true
},
"typescript.tsc.autoDetect": "off",
"testing.autoRun.mode": "rerun",
"conventionalCommits.scopes": ["tree"]
}

View file

@ -1293,6 +1293,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
get onDidFocus(): Event<void> { return this.view.onDidFocus; }
get onDidBlur(): Event<void> { return this.view.onDidBlur; }
get onDidChangeModel(): Event<void> { return Event.signal(this.model.onDidSplice); }
get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<T, TFilterData>> { return this.model.onDidChangeCollapseState; }
get onDidChangeRenderNodeCount(): Event<ITreeNode<T, TFilterData>> { return this.model.onDidChangeRenderNodeCount; }

View file

@ -341,6 +341,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
get onDidFocus(): Event<void> { return this.tree.onDidFocus; }
get onDidBlur(): Event<void> { return this.tree.onDidBlur; }
get onDidChangeModel(): Event<void> { return this.tree.onDidChangeModel; }
get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<IAsyncDataTreeNode<TInput, T> | null, TFilterData>> { return this.tree.onDidChangeCollapseState; }
get onDidUpdateOptions(): Event<IAsyncDataTreeOptionsUpdate> { return this.tree.onDidUpdateOptions; }

View file

@ -110,6 +110,10 @@ export const WorkbenchListHasSelectionOrFocus = new RawContextKey<boolean>('list
export const WorkbenchListDoubleSelection = new RawContextKey<boolean>('listDoubleSelection', false);
export const WorkbenchListMultiSelection = new RawContextKey<boolean>('listMultiSelection', false);
export const WorkbenchListSelectionNavigation = new RawContextKey<boolean>('listSelectionNavigation', false);
export const WorkbenchTreeElementCanCollapse = new RawContextKey<boolean>('treeElementCanCollapse', false);
export const WorkbenchTreeElementHasParent = new RawContextKey<boolean>('treeElementHasParent', false);
export const WorkbenchTreeElementCanExpand = new RawContextKey<boolean>('treeElementCanExpand', false);
export const WorkbenchTreeElementHasChild = new RawContextKey<boolean>('treeElementHasChild', false);
export const WorkbenchListAutomaticKeyboardNavigationKey = 'listAutomaticKeyboardNavigation';
function createScopedContextKeyService(contextKeyService: IContextKeyService, widget: ListWidget): IContextKeyService {
@ -1087,6 +1091,10 @@ class WorkbenchTreeInternals<TInput, T, TFilterData> {
private hasSelectionOrFocus: IContextKey<boolean>;
private hasDoubleSelection: IContextKey<boolean>;
private hasMultiSelection: IContextKey<boolean>;
private treeElementCanCollapse: IContextKey<boolean>;
private treeElementHasParent: IContextKey<boolean>;
private treeElementCanExpand: IContextKey<boolean>;
private treeElementHasChild: IContextKey<boolean>;
private _useAltAsMultipleSelectionModifier: boolean;
private disposables: IDisposable[] = [];
private styler: IDisposable | undefined;
@ -1117,6 +1125,11 @@ class WorkbenchTreeInternals<TInput, T, TFilterData> {
this.hasDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService);
this.hasMultiSelection = WorkbenchListMultiSelection.bindTo(this.contextKeyService);
this.treeElementCanCollapse = WorkbenchTreeElementCanCollapse.bindTo(this.contextKeyService);
this.treeElementHasParent = WorkbenchTreeElementHasParent.bindTo(this.contextKeyService);
this.treeElementCanExpand = WorkbenchTreeElementCanExpand.bindTo(this.contextKeyService);
this.treeElementHasChild = WorkbenchTreeElementHasChild.bindTo(this.contextKeyService);
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
const interestingContextKeys = new Set();
@ -1132,6 +1145,20 @@ class WorkbenchTreeInternals<TInput, T, TFilterData> {
this.updateStyleOverrides(overrideStyles);
const updateCollapseContextKeys = () => {
const focus = tree.getFocus()[0];
if (!focus) {
return;
}
const node = tree.getNode(focus);
this.treeElementCanCollapse.set(node.collapsible && !node.collapsed);
this.treeElementHasParent.set(!!tree.getParentElement(focus));
this.treeElementCanExpand.set(node.collapsible && node.collapsed);
this.treeElementHasChild.set(!!tree.getFirstElementChild(focus));
};
this.disposables.push(
this.contextKeyService,
(listService as ListService).register(tree),
@ -1150,7 +1177,10 @@ class WorkbenchTreeInternals<TInput, T, TFilterData> {
const focus = tree.getFocus();
this.hasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);
updateCollapseContextKeys();
}),
tree.onDidChangeCollapseState(updateCollapseContextKeys),
tree.onDidChangeModel(updateCollapseContextKeys),
configurationService.onDidChangeConfiguration(e => {
let newOptions: IAbstractTreeOptionsUpdate = {};
if (e.affectsConfiguration(multiSelectModifierSettingKey)) {

View file

@ -7,7 +7,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { WorkbenchListFocusContextKey, IListService, WorkbenchListSupportsMultiSelectContextKey, ListWidget, WorkbenchListHasSelectionOrFocus, getSelectionKeyboardEvent, WorkbenchListWidget, WorkbenchListSelectionNavigation } from 'vs/platform/list/browser/listService';
import { WorkbenchListFocusContextKey, IListService, WorkbenchListSupportsMultiSelectContextKey, ListWidget, WorkbenchListHasSelectionOrFocus, getSelectionKeyboardEvent, WorkbenchListWidget, WorkbenchListSelectionNavigation, WorkbenchTreeElementCanCollapse, WorkbenchTreeElementHasParent, WorkbenchTreeElementHasChild, WorkbenchTreeElementCanExpand } from 'vs/platform/list/browser/listService';
import { PagedList } from 'vs/base/browser/ui/list/listPaging';
import { equals, range } from 'vs/base/common/arrays';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
@ -252,7 +252,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.collapse',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
when: ContextKeyExpr.and(WorkbenchListFocusContextKey, ContextKeyExpr.or(WorkbenchTreeElementCanCollapse, WorkbenchTreeElementHasParent)),
primary: KeyCode.LeftArrow,
mac: {
primary: KeyCode.LeftArrow,
@ -336,7 +336,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'list.expand',
weight: KeybindingWeight.WorkbenchContrib,
when: WorkbenchListFocusContextKey,
when: ContextKeyExpr.and(WorkbenchListFocusContextKey, ContextKeyExpr.or(WorkbenchTreeElementCanExpand, WorkbenchTreeElementHasChild)),
primary: KeyCode.RightArrow,
handler: (accessor) => {
const widget = accessor.get(IListService).lastFocusedList;