Skip to content

Commit 86c490a

Browse files
committed
make tree events simpler by not exposing nodes
1 parent 866493e commit 86c490a

File tree

4 files changed

+68
-24
lines changed

4 files changed

+68
-24
lines changed

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

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
88
import { IListOptions, List, IIdentityProvider, IMultipleSelectionController, IListStyles, IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
99
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
1010
import { append, $, toggleClass } from 'vs/base/browser/dom';
11-
import { Event, Relay, chain } from 'vs/base/common/event';
11+
import { Event, Relay, chain, mapEvent } from 'vs/base/common/event';
1212
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
1313
import { KeyCode } from 'vs/base/common/keyCodes';
1414
import { ITreeModel, ITreeNode, ITreeRenderer, ITreeModelOptions } from 'vs/base/browser/ui/tree/tree';
@@ -175,24 +175,49 @@ function isInputElement(e: HTMLElement): boolean {
175175
}
176176

177177
export interface ITreeOptions<T, TFilterData = void> extends IListOptions<T>, ITreeModelOptions<T, TFilterData> { }
178-
export interface ITreeEvent<T, TFilterData> extends IListEvent<ITreeNode<T, TFilterData>> { }
179-
export interface ITreeContextMenuEvent<T, TFilterData> extends IListContextMenuEvent<ITreeNode<T, TFilterData>> { }
178+
179+
export interface ITreeEvent<T> {
180+
elements: T[];
181+
browserEvent?: UIEvent;
182+
}
183+
184+
export interface ITreeContextMenuEvent<T> {
185+
browserEvent: UIEvent;
186+
element: T | undefined;
187+
anchor: HTMLElement | { x: number; y: number; } | undefined;
188+
}
189+
190+
function asTreeEvent<T>(event: IListEvent<ITreeNode<T, any>>): ITreeEvent<T> {
191+
return {
192+
elements: event.elements.map(node => node.element),
193+
browserEvent: event.browserEvent
194+
};
195+
}
196+
197+
function asTreeContextMenuEvent<T>(event: IListContextMenuEvent<ITreeNode<T, any>>): ITreeContextMenuEvent<T> {
198+
return {
199+
element: event.element.element,
200+
browserEvent: event.browserEvent,
201+
anchor: event.anchor
202+
};
203+
}
180204

181205
export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable {
182206

183207
private view: List<ITreeNode<T, TFilterData>>;
184208
protected model: ITreeModel<T, TFilterData, TRef>;
185209
protected disposables: IDisposable[] = [];
186210

187-
readonly onDidChangeCollapseState: Event<ITreeNode<T, TFilterData>>;
188-
readonly onDidChangeRenderNodeCount: Event<ITreeNode<T, TFilterData>>;
189-
readonly onDidChangeFocus: Event<ITreeEvent<T, TFilterData>>;
190-
readonly onDidChangeSelection: Event<ITreeEvent<T, TFilterData>>;
191-
192-
readonly onContextMenu: Event<ITreeContextMenuEvent<T, TFilterData>>;
211+
get onDidChangeFocus(): Event<ITreeEvent<T>> { return mapEvent(this.view.onFocusChange, asTreeEvent); }
212+
get onDidChangeSelection(): Event<ITreeEvent<T>> { return mapEvent(this.view.onSelectionChange, asTreeEvent); }
193213

214+
get onContextMenu(): Event<ITreeContextMenuEvent<T>> { return mapEvent(this.view.onContextMenu, asTreeContextMenuEvent); }
194215
get onDidFocus(): Event<void> { return this.view.onDidFocus; }
195216
get onDidBlur(): Event<void> { return this.view.onDidBlur; }
217+
218+
get onDidChangeCollapseState(): Event<ITreeNode<T, TFilterData>> { return this.model.onDidChangeCollapseState; }
219+
get onDidChangeRenderNodeCount(): Event<ITreeNode<T, TFilterData>> { return this.model.onDidChangeRenderNodeCount; }
220+
196221
get onDidDispose(): Event<void> { return this.view.onDidDispose; }
197222

198223
constructor(
@@ -208,14 +233,9 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
208233
this.disposables.push(...treeRenderers);
209234

210235
this.view = new List(container, treeDelegate, treeRenderers, createComposedTreeListOptions(options));
211-
this.onDidChangeFocus = this.view.onFocusChange;
212-
this.onDidChangeSelection = this.view.onSelectionChange;
213-
this.onContextMenu = this.view.onContextMenu;
214236

215237
this.model = this.createModel(this.view, options);
216238
onDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState;
217-
this.onDidChangeCollapseState = this.model.onDidChangeCollapseState;
218-
this.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount;
219239

220240
if (options.mouseSupport !== false) {
221241
this.view.onMouseClick(this.onMouseClick, this, this.disposables);

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

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { ITreeOptions, ComposedTreeDelegate, createComposedTreeListOptions } from 'vs/base/browser/ui/tree/abstractTree';
6+
import { ITreeOptions, ComposedTreeDelegate, createComposedTreeListOptions, ITreeEvent, ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/abstractTree';
77
import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree';
88
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
99
import { ITreeElement, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree';
1010
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
11-
import { Emitter, Event } from 'vs/base/common/event';
11+
import { Emitter, Event, mapEvent } from 'vs/base/common/event';
1212
import { timeout } from 'vs/base/common/async';
1313

1414
export interface IDataTreeElement<T> {
@@ -95,6 +95,21 @@ class DataTreeRenderer<T, TFilterData, TTemplateData> implements ITreeRenderer<I
9595
}
9696
}
9797

98+
function asTreeEvent<T>(e: ITreeEvent<IDataTreeNode<T>>): ITreeEvent<T> {
99+
return {
100+
browserEvent: e.browserEvent,
101+
elements: e.elements.map(e => e.element)
102+
};
103+
}
104+
105+
function asTreeContextMenuEvent<T>(e: ITreeContextMenuEvent<IDataTreeNode<T>>): ITreeContextMenuEvent<T> {
106+
return {
107+
browserEvent: e.browserEvent,
108+
element: e.element.element,
109+
anchor: e.anchor
110+
};
111+
}
112+
98113
export class DataTree<T extends NonNullable<any>, TFilterData = void> implements IDisposable {
99114

100115
private tree: ObjectTree<IDataTreeNode<T>, TFilterData>;
@@ -105,6 +120,15 @@ export class DataTree<T extends NonNullable<any>, TFilterData = void> implements
105120

106121
private disposables: IDisposable[] = [];
107122

123+
get onDidChangeFocus(): Event<ITreeEvent<T>> { return mapEvent(this.tree.onDidChangeFocus, asTreeEvent); }
124+
get onDidChangeSelection(): Event<ITreeEvent<T>> { return mapEvent(this.tree.onDidChangeSelection, asTreeEvent); }
125+
126+
get onContextMenu(): Event<ITreeContextMenuEvent<T>> { return mapEvent(this.tree.onContextMenu, asTreeContextMenuEvent); }
127+
get onDidDOMFocus(): Event<void> { return this.tree.onDidFocus; }
128+
get onDidDOMBlur(): Event<void> { return this.tree.onDidBlur; }
129+
130+
get onDidDispose(): Event<void> { return this.tree.onDidDispose; }
131+
108132
constructor(
109133
container: HTMLElement,
110134
delegate: IListVirtualDelegate<T>,
@@ -125,7 +149,7 @@ export class DataTree<T extends NonNullable<any>, TFilterData = void> implements
125149

126150
this.nodes.set(null, this.root);
127151

128-
this.tree.onDidChangeCollapseState(this.onDidChangeCollapseState, this, this.disposables);
152+
this.tree.onDidChangeCollapseState(this._onDidChangeCollapseState, this, this.disposables);
129153
}
130154

131155
layout(height?: number): void {
@@ -198,7 +222,7 @@ export class DataTree<T extends NonNullable<any>, TFilterData = void> implements
198222
}
199223
}
200224

201-
private onDidChangeCollapseState(treeNode: ITreeNode<IDataTreeNode<T>, any>): void {
225+
private _onDidChangeCollapseState(treeNode: ITreeNode<IDataTreeNode<T>, any>): void {
202226
if (!treeNode.collapsed && treeNode.element.state === DataTreeNodeState.Uninitialized) {
203227
this.refreshNode(treeNode.element);
204228
}

src/vs/platform/list/browser/listService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ export class ObjectTreeResourceNavigator<T, TFilterData> extends Disposable {
594594
this._register(this.tree.onDidChangeSelection(e => this.onSelection(e)));
595595
}
596596

597-
private onFocus(e: ITreeEvent<T, TFilterData>): void {
597+
private onFocus(e: ITreeEvent<T>): void {
598598
const focus = this.tree.getFocus();
599599
this.tree.setSelection(focus, e.browserEvent);
600600

@@ -609,7 +609,7 @@ export class ObjectTreeResourceNavigator<T, TFilterData> extends Disposable {
609609
}
610610
}
611611

612-
private onSelection(e: ITreeEvent<T, TFilterData>): void {
612+
private onSelection(e: ITreeEvent<T>): void {
613613
if (!e.browserEvent || !(e.browserEvent instanceof MouseEvent)) {
614614
return;
615615
}

src/vs/workbench/parts/markers/electron-browser/markersPanel.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,8 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
305305
const markerFocusContextKey = Constants.MarkerFocusContextKey.bindTo(this.tree.contextKeyService);
306306
const relatedInformationFocusContextKey = Constants.RelatedInformationFocusContextKey.bindTo(this.tree.contextKeyService);
307307
this._register(this.tree.onDidChangeFocus(focus => {
308-
markerFocusContextKey.set(focus.elements.some(e => e.element instanceof Marker));
309-
relatedInformationFocusContextKey.set(focus.elements.some(e => e.element instanceof RelatedInformation));
308+
markerFocusContextKey.set(focus.elements.some(e => e instanceof Marker));
309+
relatedInformationFocusContextKey.set(focus.elements.some(e => e instanceof RelatedInformation));
310310
}));
311311
const focusTracker = this._register(dom.trackFocus(this.tree.getHTMLElement()));
312312
this._register(focusTracker.onDidBlur(() => {
@@ -542,15 +542,15 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
542542
this.rangeHighlightDecorations.highlightRange(selection);
543543
}
544544

545-
private onContextMenu(e: ITreeContextMenuEvent<TreeElement, FilterData>): void {
545+
private onContextMenu(e: ITreeContextMenuEvent<TreeElement>): void {
546546
if (!e.element) {
547547
return;
548548
}
549549

550550
e.browserEvent.preventDefault();
551551
e.browserEvent.stopPropagation();
552552

553-
this._getMenuActions(e.element.element).then(actions => {
553+
this._getMenuActions(e.element).then(actions => {
554554
this.contextMenuService.showContextMenu({
555555
getAnchor: () => e.anchor,
556556
getActions: () => actions,

0 commit comments

Comments
 (0)