提交 86c490a1 编写于 作者: J Joao Moreno

make tree events simpler by not exposing nodes

上级 866493ef
...@@ -8,7 +8,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; ...@@ -8,7 +8,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IListOptions, List, IIdentityProvider, IMultipleSelectionController, IListStyles, IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { IListOptions, List, IIdentityProvider, IMultipleSelectionController, IListStyles, IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent } from 'vs/base/browser/ui/list/list'; import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
import { append, $, toggleClass } from 'vs/base/browser/dom'; import { append, $, toggleClass } from 'vs/base/browser/dom';
import { Event, Relay, chain } from 'vs/base/common/event'; import { Event, Relay, chain, mapEvent } from 'vs/base/common/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes'; import { KeyCode } from 'vs/base/common/keyCodes';
import { ITreeModel, ITreeNode, ITreeRenderer, ITreeModelOptions } from 'vs/base/browser/ui/tree/tree'; import { ITreeModel, ITreeNode, ITreeRenderer, ITreeModelOptions } from 'vs/base/browser/ui/tree/tree';
...@@ -175,8 +175,32 @@ function isInputElement(e: HTMLElement): boolean { ...@@ -175,8 +175,32 @@ function isInputElement(e: HTMLElement): boolean {
} }
export interface ITreeOptions<T, TFilterData = void> extends IListOptions<T>, ITreeModelOptions<T, TFilterData> { } export interface ITreeOptions<T, TFilterData = void> extends IListOptions<T>, ITreeModelOptions<T, TFilterData> { }
export interface ITreeEvent<T, TFilterData> extends IListEvent<ITreeNode<T, TFilterData>> { }
export interface ITreeContextMenuEvent<T, TFilterData> extends IListContextMenuEvent<ITreeNode<T, TFilterData>> { } export interface ITreeEvent<T> {
elements: T[];
browserEvent?: UIEvent;
}
export interface ITreeContextMenuEvent<T> {
browserEvent: UIEvent;
element: T | undefined;
anchor: HTMLElement | { x: number; y: number; } | undefined;
}
function asTreeEvent<T>(event: IListEvent<ITreeNode<T, any>>): ITreeEvent<T> {
return {
elements: event.elements.map(node => node.element),
browserEvent: event.browserEvent
};
}
function asTreeContextMenuEvent<T>(event: IListContextMenuEvent<ITreeNode<T, any>>): ITreeContextMenuEvent<T> {
return {
element: event.element.element,
browserEvent: event.browserEvent,
anchor: event.anchor
};
}
export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable { export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable {
...@@ -184,15 +208,16 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable ...@@ -184,15 +208,16 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
protected model: ITreeModel<T, TFilterData, TRef>; protected model: ITreeModel<T, TFilterData, TRef>;
protected disposables: IDisposable[] = []; protected disposables: IDisposable[] = [];
readonly onDidChangeCollapseState: Event<ITreeNode<T, TFilterData>>; get onDidChangeFocus(): Event<ITreeEvent<T>> { return mapEvent(this.view.onFocusChange, asTreeEvent); }
readonly onDidChangeRenderNodeCount: Event<ITreeNode<T, TFilterData>>; get onDidChangeSelection(): Event<ITreeEvent<T>> { return mapEvent(this.view.onSelectionChange, asTreeEvent); }
readonly onDidChangeFocus: Event<ITreeEvent<T, TFilterData>>;
readonly onDidChangeSelection: Event<ITreeEvent<T, TFilterData>>;
readonly onContextMenu: Event<ITreeContextMenuEvent<T, TFilterData>>;
get onContextMenu(): Event<ITreeContextMenuEvent<T>> { return mapEvent(this.view.onContextMenu, asTreeContextMenuEvent); }
get onDidFocus(): Event<void> { return this.view.onDidFocus; } get onDidFocus(): Event<void> { return this.view.onDidFocus; }
get onDidBlur(): Event<void> { return this.view.onDidBlur; } get onDidBlur(): Event<void> { return this.view.onDidBlur; }
get onDidChangeCollapseState(): Event<ITreeNode<T, TFilterData>> { return this.model.onDidChangeCollapseState; }
get onDidChangeRenderNodeCount(): Event<ITreeNode<T, TFilterData>> { return this.model.onDidChangeRenderNodeCount; }
get onDidDispose(): Event<void> { return this.view.onDidDispose; } get onDidDispose(): Event<void> { return this.view.onDidDispose; }
constructor( constructor(
...@@ -208,14 +233,9 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable ...@@ -208,14 +233,9 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
this.disposables.push(...treeRenderers); this.disposables.push(...treeRenderers);
this.view = new List(container, treeDelegate, treeRenderers, createComposedTreeListOptions(options)); this.view = new List(container, treeDelegate, treeRenderers, createComposedTreeListOptions(options));
this.onDidChangeFocus = this.view.onFocusChange;
this.onDidChangeSelection = this.view.onSelectionChange;
this.onContextMenu = this.view.onContextMenu;
this.model = this.createModel(this.view, options); this.model = this.createModel(this.view, options);
onDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState; onDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState;
this.onDidChangeCollapseState = this.model.onDidChangeCollapseState;
this.onDidChangeRenderNodeCount = this.model.onDidChangeRenderNodeCount;
if (options.mouseSupport !== false) { if (options.mouseSupport !== false) {
this.view.onMouseClick(this.onMouseClick, this, this.disposables); this.view.onMouseClick(this.onMouseClick, this, this.disposables);
......
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { ITreeOptions, ComposedTreeDelegate, createComposedTreeListOptions } from 'vs/base/browser/ui/tree/abstractTree'; import { ITreeOptions, ComposedTreeDelegate, createComposedTreeListOptions, ITreeEvent, ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/abstractTree';
import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree'; import { ObjectTree } from 'vs/base/browser/ui/tree/objectTree';
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { ITreeElement, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; import { ITreeElement, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree';
import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event, mapEvent } from 'vs/base/common/event';
import { timeout } from 'vs/base/common/async'; import { timeout } from 'vs/base/common/async';
export interface IDataTreeElement<T> { export interface IDataTreeElement<T> {
...@@ -95,6 +95,21 @@ class DataTreeRenderer<T, TFilterData, TTemplateData> implements ITreeRenderer<I ...@@ -95,6 +95,21 @@ class DataTreeRenderer<T, TFilterData, TTemplateData> implements ITreeRenderer<I
} }
} }
function asTreeEvent<T>(e: ITreeEvent<IDataTreeNode<T>>): ITreeEvent<T> {
return {
browserEvent: e.browserEvent,
elements: e.elements.map(e => e.element)
};
}
function asTreeContextMenuEvent<T>(e: ITreeContextMenuEvent<IDataTreeNode<T>>): ITreeContextMenuEvent<T> {
return {
browserEvent: e.browserEvent,
element: e.element.element,
anchor: e.anchor
};
}
export class DataTree<T extends NonNullable<any>, TFilterData = void> implements IDisposable { export class DataTree<T extends NonNullable<any>, TFilterData = void> implements IDisposable {
private tree: ObjectTree<IDataTreeNode<T>, TFilterData>; private tree: ObjectTree<IDataTreeNode<T>, TFilterData>;
...@@ -105,6 +120,15 @@ export class DataTree<T extends NonNullable<any>, TFilterData = void> implements ...@@ -105,6 +120,15 @@ export class DataTree<T extends NonNullable<any>, TFilterData = void> implements
private disposables: IDisposable[] = []; private disposables: IDisposable[] = [];
get onDidChangeFocus(): Event<ITreeEvent<T>> { return mapEvent(this.tree.onDidChangeFocus, asTreeEvent); }
get onDidChangeSelection(): Event<ITreeEvent<T>> { return mapEvent(this.tree.onDidChangeSelection, asTreeEvent); }
get onContextMenu(): Event<ITreeContextMenuEvent<T>> { return mapEvent(this.tree.onContextMenu, asTreeContextMenuEvent); }
get onDidDOMFocus(): Event<void> { return this.tree.onDidFocus; }
get onDidDOMBlur(): Event<void> { return this.tree.onDidBlur; }
get onDidDispose(): Event<void> { return this.tree.onDidDispose; }
constructor( constructor(
container: HTMLElement, container: HTMLElement,
delegate: IListVirtualDelegate<T>, delegate: IListVirtualDelegate<T>,
...@@ -125,7 +149,7 @@ export class DataTree<T extends NonNullable<any>, TFilterData = void> implements ...@@ -125,7 +149,7 @@ export class DataTree<T extends NonNullable<any>, TFilterData = void> implements
this.nodes.set(null, this.root); this.nodes.set(null, this.root);
this.tree.onDidChangeCollapseState(this.onDidChangeCollapseState, this, this.disposables); this.tree.onDidChangeCollapseState(this._onDidChangeCollapseState, this, this.disposables);
} }
layout(height?: number): void { layout(height?: number): void {
...@@ -198,7 +222,7 @@ export class DataTree<T extends NonNullable<any>, TFilterData = void> implements ...@@ -198,7 +222,7 @@ export class DataTree<T extends NonNullable<any>, TFilterData = void> implements
} }
} }
private onDidChangeCollapseState(treeNode: ITreeNode<IDataTreeNode<T>, any>): void { private _onDidChangeCollapseState(treeNode: ITreeNode<IDataTreeNode<T>, any>): void {
if (!treeNode.collapsed && treeNode.element.state === DataTreeNodeState.Uninitialized) { if (!treeNode.collapsed && treeNode.element.state === DataTreeNodeState.Uninitialized) {
this.refreshNode(treeNode.element); this.refreshNode(treeNode.element);
} }
......
...@@ -594,7 +594,7 @@ export class ObjectTreeResourceNavigator<T, TFilterData> extends Disposable { ...@@ -594,7 +594,7 @@ export class ObjectTreeResourceNavigator<T, TFilterData> extends Disposable {
this._register(this.tree.onDidChangeSelection(e => this.onSelection(e))); this._register(this.tree.onDidChangeSelection(e => this.onSelection(e)));
} }
private onFocus(e: ITreeEvent<T, TFilterData>): void { private onFocus(e: ITreeEvent<T>): void {
const focus = this.tree.getFocus(); const focus = this.tree.getFocus();
this.tree.setSelection(focus, e.browserEvent); this.tree.setSelection(focus, e.browserEvent);
...@@ -609,7 +609,7 @@ export class ObjectTreeResourceNavigator<T, TFilterData> extends Disposable { ...@@ -609,7 +609,7 @@ export class ObjectTreeResourceNavigator<T, TFilterData> extends Disposable {
} }
} }
private onSelection(e: ITreeEvent<T, TFilterData>): void { private onSelection(e: ITreeEvent<T>): void {
if (!e.browserEvent || !(e.browserEvent instanceof MouseEvent)) { if (!e.browserEvent || !(e.browserEvent instanceof MouseEvent)) {
return; return;
} }
......
...@@ -305,8 +305,8 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { ...@@ -305,8 +305,8 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
const markerFocusContextKey = Constants.MarkerFocusContextKey.bindTo(this.tree.contextKeyService); const markerFocusContextKey = Constants.MarkerFocusContextKey.bindTo(this.tree.contextKeyService);
const relatedInformationFocusContextKey = Constants.RelatedInformationFocusContextKey.bindTo(this.tree.contextKeyService); const relatedInformationFocusContextKey = Constants.RelatedInformationFocusContextKey.bindTo(this.tree.contextKeyService);
this._register(this.tree.onDidChangeFocus(focus => { this._register(this.tree.onDidChangeFocus(focus => {
markerFocusContextKey.set(focus.elements.some(e => e.element instanceof Marker)); markerFocusContextKey.set(focus.elements.some(e => e instanceof Marker));
relatedInformationFocusContextKey.set(focus.elements.some(e => e.element instanceof RelatedInformation)); relatedInformationFocusContextKey.set(focus.elements.some(e => e instanceof RelatedInformation));
})); }));
const focusTracker = this._register(dom.trackFocus(this.tree.getHTMLElement())); const focusTracker = this._register(dom.trackFocus(this.tree.getHTMLElement()));
this._register(focusTracker.onDidBlur(() => { this._register(focusTracker.onDidBlur(() => {
...@@ -542,7 +542,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { ...@@ -542,7 +542,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
this.rangeHighlightDecorations.highlightRange(selection); this.rangeHighlightDecorations.highlightRange(selection);
} }
private onContextMenu(e: ITreeContextMenuEvent<TreeElement, FilterData>): void { private onContextMenu(e: ITreeContextMenuEvent<TreeElement>): void {
if (!e.element) { if (!e.element) {
return; return;
} }
...@@ -550,7 +550,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController { ...@@ -550,7 +550,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
e.browserEvent.preventDefault(); e.browserEvent.preventDefault();
e.browserEvent.stopPropagation(); e.browserEvent.stopPropagation();
this._getMenuActions(e.element.element).then(actions => { this._getMenuActions(e.element).then(actions => {
this.contextMenuService.showContextMenu({ this.contextMenuService.showContextMenu({
getAnchor: () => e.anchor, getAnchor: () => e.anchor,
getActions: () => actions, getActions: () => actions,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册