Skip to content

Commit a9c579b

Browse files
committed
tree: left/right arrow navigation
1 parent 5fd4be9 commit a9c579b

2 files changed

Lines changed: 40 additions & 21 deletions

File tree

src/vs/base/browser/ui/tree/tree.ts

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
import 'vs/css!./tree';
77
import { IDisposable, dispose, Disposable, toDisposable } from 'vs/base/common/lifecycle';
88
import { IListOptions, List, IIdentityProvider, IMultipleSelectionController } from 'vs/base/browser/ui/list/listWidget';
9-
import { TreeModel, ITreeNode, ITreeElement } from 'vs/base/browser/ui/tree/treeModel';
9+
import { TreeModel, ITreeNode, ITreeElement, getNodeLocation } from 'vs/base/browser/ui/tree/treeModel';
1010
import { IIterator, empty } from 'vs/base/common/iterator';
1111
import { IDelegate, IRenderer, IListMouseEvent } from 'vs/base/browser/ui/list/list';
1212
import { append, $ } from 'vs/base/browser/dom';
1313
import { Event, Relay, chain } from 'vs/base/common/event';
1414
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
1515
import { KeyCode } from 'vs/base/common/keyCodes';
16+
import { tail2 } from 'vs/base/common/arrays';
1617

1718
function toTreeListOptions<T>(options?: IListOptions<T>): IListOptions<ITreeNode<T>> {
1819
if (!options) {
@@ -126,17 +127,6 @@ class TreeRenderer<T, TTemplateData> implements IRenderer<ITreeNode<T>, ITreeLis
126127
}
127128
}
128129

129-
function getLocation<T>(node: ITreeNode<T>): number[] {
130-
const location = [];
131-
132-
while (node.parent) {
133-
location.push(node.parent.children.indexOf(node));
134-
node = node.parent;
135-
}
136-
137-
return location.reverse();
138-
}
139-
140130
function isInputElement(e: HTMLElement): boolean {
141131
return e.tagName === 'INPUT' || e.tagName === 'TEXTAREA';
142132
}
@@ -182,7 +172,7 @@ export class Tree<T> implements IDisposable {
182172

183173
private onMouseClick(e: IListMouseEvent<ITreeNode<T>>): void {
184174
const node = e.element;
185-
const location = getLocation(node);
175+
const location = getNodeLocation(node);
186176

187177
this.model.toggleCollapsed(location);
188178
}
@@ -198,12 +188,17 @@ export class Tree<T> implements IDisposable {
198188
}
199189

200190
const node = nodes[0];
201-
const location = getLocation(node);
202-
const didCollapse = this.model.setCollapsed(location, true);
191+
const location = getNodeLocation(node);
192+
const didChange = this.model.setCollapsed(location, true);
203193

204-
if (!didCollapse) {
205-
console.log('should focus parent');
206-
// this.view.setFocus([]);
194+
if (!didChange) {
195+
if (location.length === 1) {
196+
return;
197+
}
198+
199+
const [parentLocation] = tail2(location);
200+
const parentListIndex = this.model.getListIndex(parentLocation);
201+
this.view.setFocus([parentListIndex]);
207202
}
208203
}
209204

@@ -218,8 +213,17 @@ export class Tree<T> implements IDisposable {
218213
}
219214

220215
const node = nodes[0];
221-
const location = getLocation(node);
222-
this.model.setCollapsed(location, false);
216+
const location = getNodeLocation(node);
217+
const didChange = this.model.setCollapsed(location, false);
218+
219+
if (!didChange) {
220+
if (node.children.length === 0) {
221+
return;
222+
}
223+
224+
const [focusedIndex] = this.view.getFocus();
225+
this.view.setFocus([focusedIndex + 1]);
226+
}
223227
}
224228

225229
private onSpace(e: StandardKeyboardEvent): void {
@@ -233,7 +237,7 @@ export class Tree<T> implements IDisposable {
233237
}
234238

235239
const node = nodes[0];
236-
const location = getLocation(node);
240+
const location = getNodeLocation(node);
237241
this.model.toggleCollapsed(location);
238242
}
239243

src/vs/base/browser/ui/tree/treeModel.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ function treeNodeToElement<T>(node: IMutableTreeNode<T>): ITreeElement<T> {
8585
return { element, children, collapsed };
8686
}
8787

88+
export function getNodeLocation<T>(node: ITreeNode<T>): number[] {
89+
const location = [];
90+
91+
while (node.parent) {
92+
location.push(node.parent.children.indexOf(node));
93+
node = node.parent;
94+
}
95+
96+
return location.reverse();
97+
}
98+
8899
export class TreeModel<T> {
89100

90101
private root: IMutableTreeNode<T> = {
@@ -124,6 +135,10 @@ export class TreeModel<T> {
124135
return map(iter(deletedNodes), treeNodeToElement);
125136
}
126137

138+
getListIndex(location: number[]): number {
139+
return this.findNode(location).listIndex;
140+
}
141+
127142
setCollapsed(location: number[], collapsed: boolean): boolean {
128143
return this._setCollapsed(location, collapsed);
129144
}

0 commit comments

Comments
 (0)